Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion system/lib/wasmfs/backends/node_backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,9 @@ class NodeDirectory : public Directory {
if (_wasmfs_node_get_mode(childPath.c_str(), &mode)) {
return nullptr;
}
if (S_ISREG(mode)) {
// Allow reading from character device files too (e.g. `/dev/random`,
// `/dev/urandom`)
if (S_ISREG(mode) || S_ISCHR(mode)) {
return std::make_shared<NodeFile>(mode, getBackend(), childPath);
} else if (S_ISDIR(mode)) {
return std::make_shared<NodeDirectory>(mode, getBackend(), childPath);
Expand Down
6 changes: 4 additions & 2 deletions test/fs/test_fs_dev_random.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@ int main() {
int nread;

fp = fopen("/dev/random", "r");
nread = fread(&data, 1, byte_count, fp);
assert(fp != NULL);
nread = fread(data, 1, byte_count, fp);
assert(nread == byte_count);
fclose(fp);

fp = fopen("/dev/urandom", "r");
nread = fread(&data, 1, byte_count, fp);
assert(fp != NULL);
nread = fread(data, 1, byte_count, fp);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So you are adding an extra assert here? But it seems like if /dev/random was not openable/readable this test should already have been failing, no?

Or does this change not actually fix this test?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, the CI log for this failure has expired. IIRC, it failed with RuntimeError: memory access out of bounds, which I can reproduce using:

--- a/test/fs/test_fs_dev_random.c
+++ b/test/fs/test_fs_dev_random.c
@@ -13,14 +13,12 @@ int main() {
   int nread;
 
   fp = fopen("/dev/random", "r");
-  assert(fp != NULL);
-  nread = fread(data, 1, byte_count, fp);
+  nread = fread(data, 1, byte_count, NULL);
   assert(nread == byte_count);
   fclose(fp);
 
   fp = fopen("/dev/urandom", "r");
-  assert(fp != NULL);
-  nread = fread(data, 1, byte_count, fp);
+  nread = fread(data, 1, byte_count, NULL);
   assert(nread == byte_count);
   fclose(fp);

In other words, previously fp (FILE *) was NULL without the change to node_backend.cpp. The added asserts are intended to provide clearer failure messages.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I see, but other.test_fs_dev_random_wasmfs_rawfs cannot actually be enabled as part of this PR for some reason?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If so that sounds fair enough to me. Still nice to see fixes like this land as separate PRs.

Copy link
Copy Markdown
Collaborator Author

@kleisauke kleisauke Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other.test_fs_dev_random_wasmfs_rawfs test is enabled in this PR, but it passes because /dev and /tmp are virtualized. This virtualization is also the reason for issue #24836.

lockedDev.mountChild("random", SpecialFiles::getRandom());
lockedDev.mountChild("urandom", SpecialFiles::getURandom());

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But I don't see other.test_fs_dev_random_wasmfs_rawfs being enabled in this PR?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, sorry. I meant that it should have already been enabled by this decorator:

@with_all_fs

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For reference, see the CircleCI log at https://circleci.com/gh/emscripten-core/emscripten/1164689 for the failure.

Details
======================================================================
FAIL [0.001s]: test_fs_dev_random_wasmfs_rawfs (test_other.other)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/root/project/test/common.py", line 377, in resulting_test
    return func(self, *args)
  File "/root/project/test/decorators.py", line 324, in metafunc
    return func(self, *args, **kwargs)
  File "/root/project/test/test_other.py", line 5556, in test_fs_dev_random
    self.do_runf('fs/test_fs_dev_random.c', 'success')
  File "/root/project/test/common.py", line 1408, in do_runf
    return self._build_and_run(filename, expected_output, **kwargs)
  File "/root/project/test/common.py", line 1456, in _build_and_run
    js_output = self.run_js(js_file, engine, args,
  File "/root/project/test/common.py", line 1040, in run_js
    self.fail('JS subprocess failed (%s): %s (expected=%s).  Output:\n%s' % (error.cmd, error.returncode, assert_returncode, ret))
AssertionError: JS subprocess failed (/root/emsdk/node/22.16.0_64bit/bin/node --stack-trace-limit=50 --trace-uncaught /tmp/emtest_aitqg_pq/emscripten_test_other_piipb_5p/test_fs_dev_random.js): 1 (expected=0).  Output:
wasm://wasm/00058602:1


RuntimeError: memory access out of bounds
    at wasm://wasm/00058602:wasm-function[51]:0x1449
    at wasm://wasm/00058602:wasm-function[53]:0x1589
    at wasm://wasm/00058602:wasm-function[34]:0x913
    at wasm://wasm/00058602:wasm-function[35]:0x9f3
    at /tmp/emtest_aitqg_pq/emscripten_test_other_piipb_5p/test_fs_dev_random.js:592:12
    at callMain (/tmp/emtest_aitqg_pq/emscripten_test_other_piipb_5p/test_fs_dev_random.js:2117:15)
    at doRun (/tmp/emtest_aitqg_pq/emscripten_test_other_piipb_5p/test_fs_dev_random.js:2170:24)
    at run (/tmp/emtest_aitqg_pq/emscripten_test_other_piipb_5p/test_fs_dev_random.js:2183:5)
    at removeRunDependency (/tmp/emtest_aitqg_pq/emscripten_test_other_piipb_5p/test_fs_dev_random.js:823:11)
    at receiveInstance (/tmp/emtest_aitqg_pq/emscripten_test_other_piipb_5p/test_fs_dev_random.js:696:5)
    at receiveInstantiationResult (/tmp/emtest_aitqg_pq/emscripten_test_other_piipb_5p/test_fs_dev_random.js:713:12)
    at createWasm (/tmp/emtest_aitqg_pq/emscripten_test_other_piipb_5p/test_fs_dev_random.js:739:17)
Thrown at:
    at $func51 (wasm://wasm/00058602:1:5194)
    at $func53 (wasm://wasm/00058602:1:5514)
    at $func34 (wasm://wasm/00058602:1:2324)
    at $main (wasm://wasm/00058602:1:2548)
    at /tmp/emtest_aitqg_pq/emscripten_test_other_piipb_5p/test_fs_dev_random.js:592:12
    at callMain (/tmp/emtest_aitqg_pq/emscripten_test_other_piipb_5p/test_fs_dev_random.js:2117:15)
    at doRun (/tmp/emtest_aitqg_pq/emscripten_test_other_piipb_5p/test_fs_dev_random.js:2170:24)
    at run (/tmp/emtest_aitqg_pq/emscripten_test_other_piipb_5p/test_fs_dev_random.js:2183:5)
    at removeRunDependency (/tmp/emtest_aitqg_pq/emscripten_test_other_piipb_5p/test_fs_dev_random.js:823:11)
    at receiveInstance (/tmp/emtest_aitqg_pq/emscripten_test_other_piipb_5p/test_fs_dev_random.js:696:5)


Node.js v22.16.0


----------------------------------------------------------------------
Ran 1661 tests in 1227.050s

FAILED (failures=1, skipped=92)

assert(nread == byte_count);
fclose(fp);

Expand Down
Loading