-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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
makes FS.read async, so you can read asynchronously from stdin #3714
Conversation
What is on the stack when I see this depends on |
What is on the stack when I guess you're right making it use EmterpreterAsync will result in it only being available when called from code compiled with Emterpreter. If you would want to use in the javascript world you'd have to compile a wrapper around it. You're right Promise support is not available in IE11, although easily polyfillable. But I could change it to use callbacks, That will make it a few lines longer though. Is this something you would consider? The pull request I mean 😄 |
My concern is the code in between the C code and the If there is any JS code in the middle, we need to be sure it is safe. In general, we only call It might be safer to put the async stuff at the syscall level, look in I would definitely consider this pull, assuming the safety issue is resolved. I think we should avoid Promise, much as it would be nice to support it. |
This is the stack: so only Error
at jsStackTrace (blob:http%3A//52.6.7.231%3A3030/57073b5a-2c96-4206-b55b-ade228782e79:1161:13)
at stackTrace (blob:http%3A//52.6.7.231%3A3030/57073b5a-2c96-4206-b55b-ade228782e79:1178:22)
at Object.eval (eval at evaluate (unknown source), <anonymous>:1:1)
at Object.InjectedScript._evaluateOn (<anonymous>:904:55)
at Object.InjectedScript._evaluateAndWrap (<anonymous>:837:34)
at Object.InjectedScript.evaluateOnCallFrame (<anonymous>:963:21)
at Object.FS.createDevice.FS.registerDevice.read (blob:http%3A//52.6.7.231%3A3030/57073b5a-2c96-4206-b55b-ade228782e79:4847:6)
at Object.FS.read (blob:http%3A//52.6.7.231%3A3030/57073b5a-2c96-4206-b55b-ade228782e79:4492:43)
at _read (blob:http%3A//52.6.7.231%3A3030/57073b5a-2c96-4206-b55b-ade228782e79:6430:19)
at emterpret (blob:http%3A//52.6.7.231%3A3030/57073b5a-2c96-4206-b55b-ade228782e79:214113:11)" |
I will look into the |
Ok. If it's just |
So I figured out what doing it in syscall means 😄 I think. I will update accordingly. I'm going to make the stream in |
92ec965
to
f38b22a
Compare
I should think before I type. 😄 I will also have to change the way |
8a95756
to
348bf63
Compare
src/library_syscall.js
Outdated
var stream = SYSCALLS.getStreamFromFD(), buf = SYSCALLS.get(), count = SYSCALLS.get(); | ||
return EmterpreterAsync.handle(function (resume) { | ||
var result = FS.read(stream, {{{ makeGetSlabs('buf', 'i8', true) }}}, buf, count, null, function (bytesRead) { | ||
resume(function() { bytesRead }); |
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.
needs return
Ah yeah hi I've been at it a bit more. And I've found I also need to implement syscall 145 and there is also pread in there somewhere 😄. There's also something else broken still because allthough the test pases when I run it seperatelly it breaks. I'm away for the weekend and will be back at it Monday. I should probably not have pushed this yet. I'll let you know when I thinks it's done. |
c79552b
to
7ddc2a2
Compare
@kripken I've rebased it and added the |
src/library_syscall.js
Outdated
@@ -808,10 +861,21 @@ var SyscallsLibrary = { | |||
} | |||
return nonzero; | |||
}, | |||
#if EMTERPRETIFY_ASYNC | |||
__syscall180: function(which, varargs) { // pread64 | |||
var stream = SYSCALLS.getStreamFromFD(), buf = SYSCALLS.get(), count = SYSCALLS.get(); |
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.
what happened to the zero at the end, seen in the non-async version below?
Overall this looks functional, but the code duplication is a concern, as mentioned above. But also, in general this is more invasive than I had expected. Perhaps we need to do some refactoring to make things like this easier to do? Feels like we are doing something wrong here. |
I've added the |
@@ -810,7 +857,15 @@ var SyscallsLibrary = { | |||
}, | |||
__syscall180: function(which, varargs) { // pread64 | |||
var stream = SYSCALLS.getStreamFromFD(), buf = SYSCALLS.get(), count = SYSCALLS.get(), zero = SYSCALLS.getZero(), offset = SYSCALLS.get64(); | |||
#if EMTERPRETIFY_ASYNC |
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.
perhaps one way to reduce code duplication in places like this is if we always passed the extra parameter to FS.read
, but it was just ignored when not async. And, if we automatically added the code to add the handle, for a list of async-aware syscalls, by modifying the text. We already do similar things for SYSCALL_DEBUG
at the bottom of this file.
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.
Sure I'll try it out see how that would look/work.
Another thought on this: Perhaps we could do sync stdin reading through a new API, say |
Ok that would make things a lot less intricate/duplicated. 😄 you'd want to make the async version the default? It might be a good idea to add a few more api's to the sync one that might make it easier for people to port their existing sync code to the new api. I however don't know enough about c/c++ to make any assumptions about which those would be 😄 With permission from my employer/client I will revisit this PR soon, but it won't be this or next week. |
I was thinking that there would be just a async version for this, unless there is value in a regular one too? I'm fine with other new APIs that are useful, of course. |
Yeah sounds good to me. :) |
I think I've just run into a little problem 😄 this also makes all the other reads async. And for my case pypyjs forces me to add a lot of functions to the EMTERPRETIFY whitelist. I think we may need to rethink how to go about this. |
This PR is quite old, closing. Feel free to reopen if still relevant. |
@kripken Any suggestions for how to accomplish this today? (Feeding data into stdin via async js) |
@zone117x In general it should be easy to call async APIs in JS now using Asyncify, see Also see #9041 which is adding an example of returning a value. It is more work to make C stdin be async, since fread etc. are synchronous, which is what I think added a lot of complexity to this PR. If the C reads are replaced with calls to custom JS functions, then they can be async as in those Asyncify examples. If it would be helpful, we can add support for |
@kripken Just checking what you mean there: it would be fairly easy to add a new C func (emscripten_read_stdin) but lots of work to make the standard I have code that makes a lot of calls to Or I've seen that you can provide an stdin function with Edit: I've tried using I've found someone whose done something similar, but it involves hacking the Emscripten generated file quite a lot to add generators/yields: http://mansoft.nl/emscripten/terminal.html I've found a solution that seems to work for my usecase:
It's not pretty, but it's working for now :). |
Yes, exactly. What is "the linker's wrap option"? |
Passing in This seems to be working quite reliably. But it would only be an option when you're porting something that's quite controlled in how it reads from stdin. And some of the other functions might be harder to wrap than I'm also planning to make it more efficient by adding a custom buffer so that it doesn't have to cross the WASM/JS interface each and every call to Edit: I finished adding the buffer. In case this helps anyone else, here's the code: https://github.com/curiousdannii/emglken/blob/master/src/getc.c |
Interesting, thanks @curiousdannii , I wasn't aware of that linker option! |
This will make things like #23 (an issue from the way back when machine) a lot easier. It will also make the stdin a better browser citizen.
This implementation supports both sync and async input from the stdin. As you can see in the test. The buffer is filled with a promise that also returns the first byte and the rest of the buffer is returned to the read function immediately.
I have some failing tests but as far as I can see most of them are because I didn't have java installed.
testoutput