-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Let the event loop decide the blocking mode of File
#15930
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
Let the event loop decide the blocking mode of File
#15930
Conversation
- The `blocking` args of File constructors now defaults to `nil`. - The polling evloops now set the fd to non blocking by default. - The IOCP evloop uses OVERLAPPED IO by default.
There seems to be something wrong on macOS... Maybe the spec is blocking, somehow. EDIT: I disabled the spec on darwin, and apparently it passes. EDIT: yes, one fiber fails not_nil for some reason 😢
The error is easy to fix: wait for the thread to be terminated so either the writer is opened or it will re-raise an exception. Problem is, with less than 4 reads/writes then the spec terminates, but starting with 4+ read/write loops, then it eventually blocks 😭 Here's the evloop tracing, with execution contexts enabled:
|
It might an issue with the kqueue event loop: there's one event for fd=9 (writer) and fd=10 (reader) but only the writer seems to be resumed. EDIT: it doesn't reproduce on FreeBSD. EDIT: there's definitely something wrong on macOS:
EDIT: the EDIT: If I reverse the reader and the writer spawns, then the fibers start talking, then it waits for write, we get an kevent that fd=9 and fd=10 are ready for write, which resumes the writer that ends up waiting again... then we never get the read readiness kevent for fd=10 and it hangs forever. AFAICT: Non-blocking fifo read/write is broken on macOS for some reason. Maybe it gets confused by the two EVFILT_READ + EVFILT_WRITE kevent registration... but that doesn't happen for sockets, so that's very weird. Maybe it gets confused because the fifo file is opened by the same thread in the same process, which is maybe an odd case? |
I tried always resuming a reader along with a writer, but to no avail: it does resume both fibers but both EDIT: I tried libevent: the fifo read/write also hangs forever on macOS, aka it's macOS that's broken 🤷 |
cc20573
to
855aa85
Compare
Files now default to blocking on macOS because polling of non-blocking fifo files appears to be incorrect (at the OS level). This reinforces the argument that we should never assume any specific configuration for the system |
I investigated some more, using two threads as well as two processes (one reader, one writer) and sending/reading enough data to overflow the kernel buffers: the FIFO communication always gets stuck whenever I set I.e. non-blocking FIFO doesn't work on macOS. |
Co-authored-by: Johannes Müller <straightshoota@gmail.com>
File
This is the last missing bit from #15685.
The difference with the PoC is that opening a pipe, fifo or chardev file will still block until another thread of process has also opened the file. This was separately extracted in #15768 and obsoleted by #15871 that provides a reusable solution, leading the
blocking
arg to no longer have any purpose.The
blocking
args of File constructors now default tonil
to let the event loops decide how to configure the fd / handle.The polling evloops now set the fd to non blocking by default. There's no downside for regular disk files to have
O_NONBLOCK
set (the OS overlooks it) while not having it for other the kinds of file is an issue (it blocks).Errata: on macOS the polling evloops set the fd to blocking because polling a non-blocking fifo seems incorrect (at the OS level).
The IOCP evloop uses OVERLAPPED IO by default. Reading and writing files is now fully async on Windows 🎉