-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Handle failure of lseek in fflush #23624
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
1f6a65b
to
ac5130f
Compare
8c9d747
to
3192254
Compare
What happens in musl when seeking stdout? I would think the right thing would be returning ENOSYS or ENOTSUP or something. Does it return success and do nothing? |
The code here is only effect files that are being read-from not written-to. In linux it turns out that you can seek |
Unlike on linux (it seems) the emscripten lseek can fail for various reasons. For example, we do not support lseek on TTY or pipe file descriptors. Musl, it seems, just assumes that the seek succeeds and adjusts its internal buffers accordingly. The following (14) test expectation files were updated by running the tests with `--rebaseline`: ``` other/codesize/test_codesize_cxx_ctors1.size: 129141 => 129147 [+6 bytes / +0.00%] other/codesize/test_codesize_cxx_ctors2.size: 128553 => 128559 [+6 bytes / +0.00%] other/codesize/test_codesize_cxx_except.size: 170809 => 170815 [+6 bytes / +0.00%] other/codesize/test_codesize_cxx_except_wasm.size: 144517 => 144523 [+6 bytes / +0.00%] other/codesize/test_codesize_cxx_except_wasm_legacy.size: 142092 => 142098 [+6 bytes / +0.00%] other/codesize/test_codesize_cxx_lto.size: 122093 => 122099 [+6 bytes / +0.00%] other/codesize/test_codesize_cxx_mangle.size: 232619 => 232625 [+6 bytes / +0.00%] other/codesize/test_codesize_cxx_noexcept.size: 131704 => 131710 [+6 bytes / +0.00%] other/codesize/test_codesize_cxx_wasmfs.size: 169111 => 169117 [+6 bytes / +0.00%] other/codesize/test_codesize_files_wasmfs.size: 50049 => 50055 [+6 bytes / +0.01%] other/codesize/test_codesize_hello_O0.size: 15101 => 15105 [+4 bytes / +0.03%] other/codesize/test_codesize_minimal_O0.size: 1156 => 1160 [+4 bytes / +0.35%] other/test_unoptimized_code_size.wasm.size: 15101 => 15105 [+4 bytes / +0.03%] other/test_unoptimized_code_size_strict.wasm.size: 15101 => 15105 [+4 bytes / +0.03%] Average change: +0.03% (+0.00% - +0.35%) ```
See #23627 for more the |
Should we consider copying that behavior for the stdin device instead of making this change? Since otherwise there is an observable difference in the behavior when seeking |
Can you explain what you mean exactly? Are you suggesting that we update emscripten to allow stdin to support seeking? I think that would be much bigger change and without much benefit (as I mentioned in #23624 (comment)). I also think its fairly reasonable that stdin and stdout don't support seeking, no? Here is the code for stdin handling BTW: emscripten/src/lib/libfs_shared.js Lines 107 to 177 in 242af00
|
I agree that they shouldn't. But I think if linux does something unreasonable we should try to do the same unreasonable thing whenever possible. |
But yeah if it's more effort than it's worth that is fair. |
I think this would be enough to make stdin seekable in the JS fs: --- a/src/lib/libfs.js
+++ b/src/lib/libfs.js
@@ -1493,7 +1493,7 @@ FS.staticInit();
// have been overwritten we create a unique device for
// them instead.
if (input) {
- FS.createDevice('/dev', 'stdin', input);
+ FS.createDevice('/dev', 'stdin', input, null, {seekable: true});
} else {
FS.symlink('/dev/tty', '/dev/stdin');
}
@@ -1659,7 +1659,7 @@ FS.staticInit();
FS.chmod(node, mode);
}
},
- createDevice(parent, name, input, output) {
+ createDevice(parent, name, input, output, opts) {
var path = PATH.join2(typeof parent == 'string' ? parent : FS.getPath(parent), name);
var mode = FS_getMode(!!input, !!output);
FS.createDevice.major ??= 64;
@@ -1668,7 +1668,7 @@ FS.staticInit();
// the old behavior.
FS.registerDevice(dev, {
open(stream) {
- stream.seekable = false;
+ stream.seekable = opts.seekable ?? false;
},
close(stream) {
// flush any pending line data |
But maybe that will cause a hard crash when you try to seek it, I didn't try it =) |
I don't think emscripten should go out of its way to emulate every linux corner case like this. At least not until we have evidence that real world programs depend on them. Our libc for example, even though its based on musl, lacks most linux-specific stuff. We can make exceptions if we find a lot of real world code the needs it but in general we don't support linux-specific stuff. |
Its more complex than that I fear. See Lines 62 to 85 in 242af00
get_char works here.
|
Okay I think I finally understand. You're saying that |
The linux stdin fd certainly seems to be doing that yes. At least in my tests on alpine linux. I'm not sure why. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the explanation @sbc100. I think this makes sense to me now. It might be helpful if you could add a summary of your answers to my questions to the comment.
I updated the comment. Thanks for the review @hoodmane, and thanks for all your recent contributions. |
Actually I turns out that calling fflush on stdin is undefined behaviour: https://en.cppreference.com/w/c/io/fflush: "For input streams (and for update streams on which the last operation was input), the behavior is undefined.". Should we revert this? |
I would lean towards reverting. This adds code size and increases the diff vs upstream musl, and in return for something very minor. |
Reverts #23624 This turned out to be a fix for something that is undefined behaviour.
Unlike on linux (it seems) the emscripten lseek can fail for various reasons. For example, we do not support lseek on TTY or pipe file descriptors.
Musl, it seems, just assumes that the seek succeeds and adjusts its internal buffers accordingly. This PR update fflush such that it can handle the failure of lseek.
The alternative to this approach would be to add
seek
support to file our stdin implementation but that looks like a bigger change. Since it seems reasonable for stdout and stdin to not be seekable updating musl to handle this case seems like the right thing to do for now. If we find a other code in the wild that depends on stdin supporting lseek we can reconsider.The following (14) test expectation files were updated by
running the tests with
--rebaseline
:Fixes: #21791