loop: add pending work to loop-alive check (#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: https://github.com/libuv/libuv/pull/3234
Refs: https://github.com/libuv/libuv/issues/3101
Refs: https://github.com/libuv/libuv/pull/3308
This commit is contained in:
Jameson Nash 2022-02-13 00:12:11 -05:00 committed by GitHub
parent 7a68f5ab4b
commit 939a05633f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 59 additions and 59 deletions

View File

@ -334,35 +334,36 @@ int uv_backend_fd(const uv_loop_t* loop) {
}
int uv_backend_timeout(const uv_loop_t* loop) {
if (loop->stop_flag != 0)
return 0;
if (!uv__has_active_handles(loop) && !uv__has_active_reqs(loop))
return 0;
if (!QUEUE_EMPTY(&loop->idle_handles))
return 0;
if (!QUEUE_EMPTY(&loop->pending_queue))
return 0;
if (loop->closing_handles)
return 0;
return uv__next_timeout(loop);
}
static int uv__loop_alive(const uv_loop_t* loop) {
return uv__has_active_handles(loop) ||
uv__has_active_reqs(loop) ||
!QUEUE_EMPTY(&loop->pending_queue) ||
loop->closing_handles != NULL;
}
static int uv__backend_timeout(const uv_loop_t* loop) {
if (loop->stop_flag == 0 &&
/* uv__loop_alive(loop) && */
(uv__has_active_handles(loop) || uv__has_active_reqs(loop)) &&
QUEUE_EMPTY(&loop->pending_queue) &&
QUEUE_EMPTY(&loop->idle_handles) &&
loop->closing_handles == NULL)
return uv__next_timeout(loop);
return 0;
}
int uv_backend_timeout(const uv_loop_t* loop) {
if (QUEUE_EMPTY(&loop->watcher_queue))
return uv__backend_timeout(loop);
/* Need to call uv_run to update the backend fd state. */
return 0;
}
int uv_loop_alive(const uv_loop_t* loop) {
return uv__loop_alive(loop);
return uv__loop_alive(loop);
}

View File

@ -395,23 +395,28 @@ int uv_loop_fork(uv_loop_t* loop) {
}
static int uv__loop_alive(const uv_loop_t* loop) {
return uv__has_active_handles(loop) ||
uv__has_active_reqs(loop) ||
loop->pending_reqs_tail != NULL ||
loop->endgame_handles != NULL;
}
int uv_loop_alive(const uv_loop_t* loop) {
return uv__loop_alive(loop);
}
int uv_backend_timeout(const uv_loop_t* loop) {
if (loop->stop_flag != 0)
return 0;
if (!uv__has_active_handles(loop) && !uv__has_active_reqs(loop))
return 0;
if (loop->pending_reqs_tail)
return 0;
if (loop->endgame_handles)
return 0;
if (loop->idle_handles)
return 0;
return uv__next_timeout(loop);
if (loop->stop_flag == 0 &&
/* uv__loop_alive(loop) && */
(uv__has_active_handles(loop) || uv__has_active_reqs(loop)) &&
loop->pending_reqs_tail == NULL &&
loop->idle_handles == NULL &&
loop->endgame_handles == NULL)
return uv__next_timeout(loop);
return 0;
}
@ -581,18 +586,6 @@ static void uv__poll(uv_loop_t* loop, DWORD timeout) {
}
static int uv__loop_alive(const uv_loop_t* loop) {
return uv__has_active_handles(loop) ||
uv__has_active_reqs(loop) ||
loop->endgame_handles != NULL;
}
int uv_loop_alive(const uv_loop_t* loop) {
return uv__loop_alive(loop);
}
int uv_run(uv_loop_t *loop, uv_run_mode mode) {
DWORD timeout;
int r;

View File

@ -28,7 +28,7 @@ TEST_IMPL(loop_update_time) {
start = uv_now(uv_default_loop());
while (uv_now(uv_default_loop()) - start < 1000)
ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_NOWAIT));
ASSERT_EQ(0, uv_run(uv_default_loop(), UV_RUN_NOWAIT));
MAKE_VALGRIND_HAPPY();
return 0;
@ -43,20 +43,26 @@ TEST_IMPL(loop_backend_timeout) {
uv_timer_t timer;
int r;
r = uv_timer_init(loop, &timer);
ASSERT(r == 0);
/* The default loop has some internal watchers to initialize. */
loop->active_handles++;
r = uv_run(loop, UV_RUN_NOWAIT);
ASSERT_EQ(r, 1);
loop->active_handles--;
ASSERT_EQ(uv_loop_alive(loop), 0);
ASSERT(!uv_loop_alive(loop));
ASSERT(uv_backend_timeout(loop) == 0);
r = uv_timer_init(loop, &timer);
ASSERT_EQ(r, 0);
ASSERT_EQ(uv_loop_alive(loop), 0);
ASSERT_EQ(uv_backend_timeout(loop), 0);
r = uv_timer_start(&timer, cb, 1000, 0); /* 1 sec */
ASSERT(r == 0);
ASSERT(uv_backend_timeout(loop) > 100); /* 0.1 sec */
ASSERT(uv_backend_timeout(loop) <= 1000); /* 1 sec */
ASSERT_EQ(r, 0);
ASSERT_EQ(uv_backend_timeout(loop), 1000);
r = uv_run(loop, UV_RUN_DEFAULT);
ASSERT(r == 0);
ASSERT(uv_backend_timeout(loop) == 0);
ASSERT_EQ(r, 0);
ASSERT_EQ(uv_backend_timeout(loop), 0);
MAKE_VALGRIND_HAPPY();
return 0;