Skip to content

Commit 85793a2

Browse files
authored
[WasmFS] Support errors in open (#17536)
Change the signature of the `open` method in the backend API to support returning error codes. Also refactor how this method is called since it was previously called in the `OpenFileState` constructor, but constructors are not fallible.
1 parent ca51766 commit 85793a2

16 files changed

+179
-43
lines changed

src/library_wasmfs_opfs.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,9 @@ mergeInto(LibraryManager.library, {
232232
}
233233
accessID = wasmfsOPFSAllocate(wasmfsOPFSAccessHandles, accessHandle);
234234
} catch (e) {
235-
if (e.name === "InvalidStateError") {
235+
// TODO: Presumably only one of these will appear in the final API?
236+
if (e.name === "InvalidStateError" ||
237+
e.name === "NoModificationAllowedError") {
236238
accessID = -1;
237239
} else {
238240
throw e;

system/lib/wasmfs/backends/node_backend.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -156,10 +156,7 @@ class NodeFile : public DataFile {
156156
WASMFS_UNREACHABLE("TODO: implement NodeFile::setSize");
157157
}
158158

159-
void open(oflags_t flags) override {
160-
// TODO: Properly report errors.
161-
state.open(flags);
162-
}
159+
int open(oflags_t flags) override { return state.open(flags); }
163160

164161
void close() override { state.close(); }
165162

system/lib/wasmfs/backends/opfs_backend.cpp

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -272,12 +272,7 @@ class OPFSFile : public DataFile {
272272
}
273273
}
274274

275-
void open(oflags_t flags) override {
276-
if (auto err = state.open(proxy, fileID, flags); err < 0) {
277-
// TODO: Proper error reporting.
278-
assert(false && "error during open");
279-
}
280-
}
275+
int open(oflags_t flags) override { return state.open(proxy, fileID, flags); }
281276

282277
void close() override { state.close(proxy); }
283278

system/lib/wasmfs/backends/proxied_file_backend.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@ class ProxiedFile : public DataFile {
2222
emscripten::ProxyWorker& proxy;
2323
std::shared_ptr<DataFile> baseFile;
2424

25-
void open(oflags_t flags) override {
26-
proxy([&]() { baseFile->locked().open(flags); });
25+
int open(oflags_t flags) override {
26+
int err;
27+
proxy([&]() { err = baseFile->locked().open(flags); });
28+
return err;
2729
}
2830

2931
void close() override {

system/lib/wasmfs/file.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,8 @@ class DataFile : public File {
129129
protected:
130130
// Notify the backend when this file is opened or closed. The backend is
131131
// responsible for keeping files accessible as long as they are open, even if
132-
// they are unlinked.
133-
// TODO: Report errors.
134-
virtual void open(oflags_t flags) = 0;
132+
// they are unlinked. Returns 0 on success or a negative error code.
133+
virtual int open(oflags_t flags) = 0;
135134
virtual void close() = 0;
136135

137136
// Return the accessed length or a negative error code. It is not an error to
@@ -289,7 +288,7 @@ class DataFile::Handle : public File::Handle {
289288
Handle(std::shared_ptr<File> dataFile) : File::Handle(dataFile) {}
290289
Handle(Handle&&) = default;
291290

292-
void open(oflags_t flags) { getFile()->open(flags); }
291+
[[nodiscard]] int open(oflags_t flags) { return getFile()->open(flags); }
293292
void close() { getFile()->close(); }
294293

295294
ssize_t read(uint8_t* buf, size_t len, off_t offset) {

system/lib/wasmfs/file_table.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,15 @@
1212
namespace wasmfs {
1313

1414
FileTable::FileTable() {
15-
entries.push_back(
16-
std::make_shared<OpenFileState>(0, O_RDONLY, SpecialFiles::getStdin()));
17-
entries.push_back(
18-
std::make_shared<OpenFileState>(0, O_WRONLY, SpecialFiles::getStdout()));
19-
entries.push_back(
20-
std::make_shared<OpenFileState>(0, O_WRONLY, SpecialFiles::getStderr()));
15+
entries.emplace_back();
16+
(void)OpenFileState::create(
17+
SpecialFiles::getStdin(), O_RDONLY, entries.back());
18+
entries.emplace_back();
19+
(void)OpenFileState::create(
20+
SpecialFiles::getStdout(), O_WRONLY, entries.back());
21+
entries.emplace_back();
22+
(void)OpenFileState::create(
23+
SpecialFiles::getStderr(), O_WRONLY, entries.back());
2124
}
2225

2326
std::shared_ptr<OpenFileState> FileTable::Handle::getEntry(__wasi_fd_t fd) {

system/lib/wasmfs/file_table.h

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,25 +32,40 @@ template<typename T> bool addWillOverFlow(T a, T b) {
3232

3333
class OpenFileState : public std::enable_shared_from_this<OpenFileState> {
3434
std::shared_ptr<File> file;
35-
off_t position;
35+
off_t position = 0;
3636
oflags_t flags; // RD_ONLY, WR_ONLY, RDWR
37+
3738
// An OpenFileState needs a mutex if there are concurrent accesses on one open
3839
// file descriptor. This could occur if there are multiple seeks on the same
3940
// open file descriptor.
4041
std::recursive_mutex mutex;
4142

43+
// We can't make the constructor private because std::make_shared needs to be
44+
// able to call it, but we can make it unusable publicly.
45+
struct private_key {
46+
explicit private_key(int) {}
47+
};
48+
4249
public:
43-
OpenFileState(size_t position, oflags_t flags, std::shared_ptr<File> file)
44-
: position(position), flags(flags), file(file) {
50+
OpenFileState(private_key, oflags_t flags, std::shared_ptr<File> file)
51+
: flags(flags), file(file) {}
52+
53+
~OpenFileState() {
4554
if (auto f = file->dynCast<DataFile>()) {
46-
f->locked().open(flags & O_ACCMODE);
55+
f->locked().close();
4756
}
4857
}
4958

50-
~OpenFileState() {
59+
[[nodiscard]] static int create(std::shared_ptr<File> file,
60+
oflags_t flags,
61+
std::shared_ptr<OpenFileState>& out) {
5162
if (auto f = file->dynCast<DataFile>()) {
52-
f->locked().close();
63+
if (int err = f->locked().open(flags & O_ACCMODE)) {
64+
return err;
65+
}
5366
}
67+
out = std::make_shared<OpenFileState>(private_key{0}, flags, file);
68+
return 0;
5469
}
5570

5671
class Handle {

system/lib/wasmfs/js_impl_backend.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ class JSImplFile : public DataFile {
7777
}
7878

7979
// TODO: Notify the JS about open and close events?
80-
void open(oflags_t) override {}
80+
int open(oflags_t) override { return 0; }
8181
void close() override {}
8282

8383
ssize_t write(const uint8_t* buf, size_t len, off_t offset) override {

system/lib/wasmfs/memory_backend.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ namespace wasmfs {
1919
class MemoryFile : public DataFile {
2020
std::vector<uint8_t> buffer;
2121

22-
void open(oflags_t) override {}
22+
int open(oflags_t) override { return 0; }
2323
void close() override {}
2424
ssize_t write(const uint8_t* buf, size_t len, off_t offset) override;
2525
ssize_t read(uint8_t* buf, size_t len, off_t offset) override;

system/lib/wasmfs/pipe_backend.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ using PipeData = std::queue<uint8_t>;
2323
class PipeFile : public DataFile {
2424
std::shared_ptr<PipeData> data;
2525

26-
void open(oflags_t) override {}
26+
int open(oflags_t) override { return 0; }
2727
void close() override {}
2828

2929
ssize_t write(const uint8_t* buf, size_t len, off_t offset) override {

0 commit comments

Comments
 (0)