loop: better align order-of-events behavior between platforms (#3598)

Previously, Windows would always defer event processing to the loop
after they were received. This could cause confusion for users who were
using prepare and idle callbacks, as seen from this bug in nodejs[^1] and
this discussion in libuv[^2], and even some discrepancies in the libuv
tests too[^3].

[^1]: https://github.com/nodejs/node/pull/42340
[^2]: https://github.com/libuv/libuv/discussions/3550
[^3]: See change to test-spawn.c in this PR

So rather than declare those usages to be wrong, we change libuv to meet
those users expectations.

Replaces: https://github.com/libuv/libuv/pull/3585
This commit is contained in:
Jameson Nash 2022-05-13 06:41:33 -04:00 committed by GitHub
parent ec67735412
commit ee3718dd71
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 11 additions and 5 deletions

View File

@ -404,6 +404,11 @@ int uv_run(uv_loop_t* loop, uv_run_mode mode) {
uv__io_poll(loop, timeout);
/* Process immediate callbacks (e.g. write_cb) a small fixed number of
* times to avoid loop starvation.*/
for (r = 0; r < 8 && !QUEUE_EMPTY(&loop->pending_queue); r++)
uv__run_pending(loop);
/* Run one final update on the provider_idle_time in case uv__io_poll
* returned because the timeout expired, but no events were received. This
* call will be ignored if the provider_entry_time was either never set (if

View File

@ -617,6 +617,11 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) {
else
uv__poll_wine(loop, timeout);
/* Process immediate callbacks (e.g. write_cb) a small fixed number of
* times to avoid loop starvation.*/
for (r = 0; r < 8 && loop->pending_reqs_tail != NULL; r++)
uv__process_reqs(loop);
/* Run one final update on the provider_idle_time in case uv__poll*
* returned because the timeout expired, but no events were received. This
* call will be ignored if the provider_entry_time was either never set (if

View File

@ -102,8 +102,7 @@ TEST_IMPL(pipe_set_non_blocking) {
ASSERT(n == UV_EAGAIN); /* E_NOTIMPL */
ASSERT(0 == uv_write(&write_req, (uv_stream_t*) &pipe_handle, &buf, 1, write_cb));
ASSERT_NOT_NULL(write_req.handle);
ASSERT(1 == uv_run(uv_default_loop(), UV_RUN_ONCE)); /* queue write_cb */
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE)); /* process write_cb */
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE));
ASSERT_NULL(write_req.handle); /* check for signaled completion of write_cb */
n = buf.len;
#endif

View File

@ -1675,9 +1675,6 @@ TEST_IMPL(closed_fd_events) {
ASSERT(req.result == 1);
uv_fs_req_cleanup(&req);
#ifdef _WIN32
ASSERT(1 == uv_run(uv_default_loop(), UV_RUN_ONCE));
#endif
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE));
/* should have received just one byte */