-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Async only exhausts handle when callback isn't removed #19764
Comments
Hm, interesting how you arrived at this. The current semantics make sense: you are telling the event loop to run two callbacks whenever the FD becomes readable. You are "extinguishing" it in the first callback by reading all the data in it, and then you're blocking your thread by calling read again when the FD is no longer readable. What you should do instead is make your FD non-blocking, that way your second read will return EAGAIN and you can then return We can and should definitely document this better |
Yeah the current semantics makes sense, if they had been documented. It wasn't immediately obvious that this is how the system worked, I just assumed that it would run either just the first one, a random one, or round-robin them, all of which should've worked fine with the way I was doing it. The problem here is that I'm wrapping a C library and I don't read directly from the handle. When the handle can be read from I call |
Can you elaborate more on what this |
The library I'm wrapping is libcoap. As you can see from the second way of handling IO listed in the description section you can |
What I think you want is to follow the "Method Two - epoll_wait() based on monitorable file descriptor" example. They even call |
Yes, that is indeed what you'd want to do, and what I was doing. In my code I didn't have the blocking behaviour I used to demonstrate the issue above. The problem in my case was elsewhere, but it stemmed from a misunderstanding of how the callback from |
I was trying to wrap a C library in Nims async capabilities. It all seemed to work fine, but when I tried to run more than one action at the same time it locked up. After some investigation I've concluded that it is caused by some subtle undocumented behaviour, potentially just a straight up bug. Consider the following example (only works on Linux, or other systems with async stdin):
When running the program this will happily print "ping" every five seconds. If you write something to the terminal in echos it back out, but then it stops sending the pings. What is happening here is that the second callback is blocking on trying to read stdin. The execution looks something like this:
As we can see the second callback is also run when the standard input is ready for reading, even though the first handler exhausted the handle.
The related code is found in asyncdispatch:1265:1276 and reads (at the time of writing):
If the callback handler returns
false
, meaning that it should not be run again, the rest of the callbacks are simply added to the new queue and will not be run until further reads are possible. However if the handler returnstrue
as in the example above, meaning that the handler should not be removed it will continue processing the other callbacks. The relevant documentation foraddRead
is:No mention of this exhaustion-handling at all. This should either be documented, or it should be fixed so that only one of the callbacks are ever called for a single event. At least on POSIX the selector should just immediately fire again if there is still data to be read.
The text was updated successfully, but these errors were encountered: