core: uv_backend_timeout should return 0 when has pending watchers#3234
core: uv_backend_timeout should return 0 when has pending watchers#3234XeCycle wants to merge 1 commit into
Conversation
|
Oh, the same |
|
The problem description makes sense to me, although I have not thought about it closely enough to suggest a solution. It sounds like you are on the right track though. Perhaps |
|
Updated to split |
Sounds interesting, basically that means to split some work from
When using Arguably this case looks niche, but seems the only way to fix the whole embedding problem is to alter EDIT, not the only way, we can also change |
|
IIUC, this will fix #3101 |
|
@vtjnash this is only a partial fix. As described above, the "start poll in prepare --- stop in check" pattern will become a busy loop with this change; maybe we can call it "working", but barely useful. Still better than nothing at all, though. I suspect that pattern may be rare, because it incurs unnecessary syscalls at every iteration, so performance sensitive users probably have avoided it; but I have no statistics to support my guess. Summing up options discussed so far:
Maybe we can go with 1 for now and postpone 3 for v2. I'm ready to get back and add tests for this if you are happy with this change; afraid I don't have enough time to carry out option 3 however. |
|
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
Pending work may be either (on any platform) pending_queue callbacks or (on unix) watcher_queue handles to add to the io poll object. Previously, we might have gotten somewhat stuck if the user caused an event to be added to one of these in the idle or prepare callbacks, or was embedding libuv. Refs: libuv#3234 Refs: libuv#3101 Refs: libuv#3308
Pending work may be either (on any platform) pending_queue callbacks or (on unix) watcher_queue handles to add to the io poll object. Previously, we might have gotten somewhat stuck if the user caused an event to be added to one of these in the idle or prepare callbacks, or was embedding libuv. Refs: libuv#3234 Refs: libuv#3101 Refs: libuv#3308
Pending work may be either (on any platform) pending_queue callbacks or (on unix) watcher_queue handles to add to the io poll object. Previously, we might have gotten somewhat stuck if the user caused an event to be added to one of these in the idle or prepare callbacks, or was embedding libuv. Refs: #3234 Refs: #3101 Refs: #3308
|
Fixed by #3466 |
Pending work may be either (on any platform) pending_queue callbacks or (on unix) watcher_queue handles to add to the io poll object. Previously, we might have gotten somewhat stuck if the user caused an event to be added to one of these in the idle or prepare callbacks, or was embedding libuv. Refs: libuv#3234 Refs: libuv#3101 Refs: libuv#3308
Pending work may be either (on any platform) pending_queue callbacks or (on unix) watcher_queue handles to add to the io poll object. Previously, we might have gotten somewhat stuck if the user caused an event to be added to one of these in the idle or prepare callbacks, or was embedding libuv. Refs: libuv/libuv#3234 Refs: libuv/libuv#3101 Refs: libuv/libuv#3308
Pending work may be either (on any platform) pending_queue callbacks or (on unix) watcher_queue handles to add to the io poll object. Previously, we might have gotten somewhat stuck if the user caused an event to be added to one of these in the idle or prepare callbacks, or was embedding libuv. Refs: libuv/libuv#3234 Refs: libuv/libuv#3101 Refs: libuv/libuv#3308
Looks like when a new FD is going to be
EPOLL_CTL_ADDed, it is first pushed towatcher_queue; a later call touv__io_pollwould actually register them to kernel. But withUV_RUN_NOWAITthe iteration stops at an unfortunate point where we may have "runnable task" before blocking, anduv_backend_timeoutfailed to report this kind of work.Some context: I'm embedding libuv into python's asyncio loop, to integrate existing codebase into python. (Not really performance-sensitive, so not using https://github.com/MagicStack/uvloop/; this project is not really ready for such kind of loop sharing yet) My approach is to write a custom
Selector(implements pythonselectors.BaseSelector) that simply callsuv_run(UV_RUN_NOWAIT)right before calling callingepoll_wait(epfd_of_python_asyncio), using combined timeout from libuv and python. Before this patchuv_backend_timeoutmay return -1 even when there are work inwatcher_queue, and the relevant FDs are not registered to kernel, causing an infinite fruitless wait.Draft because I'm not sure whether this is the best approach; with this patch downstream caller would just go back and call another
uv_run(UV_RUN_NOWAIT), but this may incur an unnecessary call toepoll_wait. Maybe we could modify the execution order and split upuv__io_pollso that we check for stop right before callingepoll_wait, but that can be a massive change.Dear maintainers if you decide this approach is good enough I can take a little time to add tests for it.