Skip to content

Commit f64886f

Browse files
vtjnashliujinye-sys
authored andcommitted
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]: nodejs/node#42340 [^2]: libuv/libuv#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: libuv/libuv#3585
1 parent 0f7df9b commit f64886f

File tree

4 files changed

+11
-5
lines changed

4 files changed

+11
-5
lines changed

src/unix/core.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,11 @@ int uv_run(uv_loop_t* loop, uv_run_mode mode) {
404404

405405
uv__io_poll(loop, timeout);
406406

407+
/* Process immediate callbacks (e.g. write_cb) a small fixed number of
408+
* times to avoid loop starvation.*/
409+
for (r = 0; r < 8 && !QUEUE_EMPTY(&loop->pending_queue); r++)
410+
uv__run_pending(loop);
411+
407412
/* Run one final update on the provider_idle_time in case uv__io_poll
408413
* returned because the timeout expired, but no events were received. This
409414
* call will be ignored if the provider_entry_time was either never set (if

src/win/core.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,11 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) {
617617
else
618618
uv__poll_wine(loop, timeout);
619619

620+
/* Process immediate callbacks (e.g. write_cb) a small fixed number of
621+
* times to avoid loop starvation.*/
622+
for (r = 0; r < 8 && loop->pending_reqs_tail != NULL; r++)
623+
uv__process_reqs(loop);
624+
620625
/* Run one final update on the provider_idle_time in case uv__poll*
621626
* returned because the timeout expired, but no events were received. This
622627
* call will be ignored if the provider_entry_time was either never set (if

test/test-pipe-set-non-blocking.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,7 @@ TEST_IMPL(pipe_set_non_blocking) {
102102
ASSERT(n == UV_EAGAIN); /* E_NOTIMPL */
103103
ASSERT(0 == uv_write(&write_req, (uv_stream_t*) &pipe_handle, &buf, 1, write_cb));
104104
ASSERT_NOT_NULL(write_req.handle);
105-
ASSERT(1 == uv_run(uv_default_loop(), UV_RUN_ONCE)); /* queue write_cb */
106-
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE)); /* process write_cb */
105+
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE));
107106
ASSERT_NULL(write_req.handle); /* check for signaled completion of write_cb */
108107
n = buf.len;
109108
#endif

test/test-spawn.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1675,9 +1675,6 @@ TEST_IMPL(closed_fd_events) {
16751675
ASSERT(req.result == 1);
16761676
uv_fs_req_cleanup(&req);
16771677

1678-
#ifdef _WIN32
1679-
ASSERT(1 == uv_run(uv_default_loop(), UV_RUN_ONCE));
1680-
#endif
16811678
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE));
16821679

16831680
/* should have received just one byte */

0 commit comments

Comments
 (0)