-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Support asynchronous IO.pipe
on Windows
#13362
Support asynchronous IO.pipe
on Windows
#13362
Conversation
spec/std/http/spec_helper.cr
Outdated
{% unless flag?(:win32) %} | ||
server_io.close | ||
if exc = done.receive | ||
raise exc | ||
end | ||
{% end %} |
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.
It seems one of the IO
s was trying to flush to a closed stream if this line is present. I have no idea this broke the OAuth2 specs nor why it is necessary on existing platforms
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.
Yeah, this should require some investigation. The close behaviour should not be platform-specific.
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.
It looks like the current fiber is unconditionally scheduled at a later time even if WriteFile
finishes synchronously, despite FILE_FLAG_OVERLAPPED
being used. This causes this ensure
block to run immediately when the HTTP::Server::Response
is closed
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.
Now I'm wondering: if socket operations like WSASend
complete immediately, we also might not need to unconditionally reschedule inside #wsa_overlapped_operation
either
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.
Great find! That seems like the piece we've been missing 🚀
My main worry is the behaviour of async (overlapped) streams being passed to a new process. As described in #6957 (comment) point 3. this would be problematic. For example, the following program has lead to crashes with this patch: reader, writer = IO.pipe
Process.run("cmd.exe", output: writer)
writer.close
puts reader.gets_to_end It doesn't always crash. And I haven't been able to dig more into what's going on. When it's crashing it seems to take the shell down with it. And nothing is written to stdout nor stderr. So this might need more investigation. |
I tried the above on Windows 11 22H2 22621.1555 and it never crashed. Can |
Hm, after more digging it seems that the compiler (or the wrapper script?) is actually breaking. Not the program itself (I was using @kubo Do you have any comment? Maybe we need to consider something we have missed so far? |
I checked it using this gist code. As far as I ran the code, asynchronous pipe handles can be passed to child processes as stdio handles. As for strikethrough text in #6957 (comment) it seems that I made a mistake. Perhaps it was fixed by MS or probably I wrote wrong code. |
spec/std/http/spec_helper.cr
Outdated
{% unless flag?(:win32) %} | ||
server_io.close | ||
if exc = done.receive | ||
raise exc | ||
end | ||
{% end %} |
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.
Yeah, this should require some investigation. The close behaviour should not be platform-specific.
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.
LGTM
This PR makes
IO.pipe
returnIO::FileDescriptor
s whose#read
and#write
run asynchronously. Closes #6957. Fixes #12718. Fixes #9893 (comment).IO.pipe
is backed by Win32 named pipes with unique names. They differ from Unix pipes in at least two substantial ways:ERROR_BROKEN_PIPE
, so that error value is used for this purpose instead and not treated as a hard error.Asynchronous I/O for regular files might be as simple as passing
LibC::FILE_FLAG_OVERLAPPED
toLibC.CreateFileW
, which I haven't tried. (They will signal EOFs.) The consoleSTDIN
andSTDOUT
are also still synchronous and might require separate threads as described in #6957 (comment).Also it seems this is not enough to get the playground running on Windows.