From 24d1d0802d2c6ff6d0b2e556c0c2b1a5ebf33493 Mon Sep 17 00:00:00 2001 From: Trevor Norris Date: Wed, 14 Jun 2023 10:25:55 -0600 Subject: [PATCH] src: don't run timers if loop is stopped/unref'd (#4048) The initial run of timers shouldn't happen if uv_stop() has been run before uv_run() was called, and for backwards compatibility they also shouldn't run if they have been unref'd before calling uv_run(). --- src/unix/core.c | 5 ++--- src/win/core.c | 5 ++--- test/test-list.h | 4 ++++ test/test-loop-stop.c | 11 +++++++++++ test/test-timer.c | 12 ++++++++++++ 5 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/unix/core.c b/src/unix/core.c index 4db2b0af..0756364f 100644 --- a/src/unix/core.c +++ b/src/unix/core.c @@ -424,9 +424,8 @@ int uv_run(uv_loop_t* loop, uv_run_mode mode) { * while loop for UV_RUN_DEFAULT. Otherwise timers only need to be executed * once, which should be done after polling in order to maintain proper * execution order of the conceptual event loop. */ - if (mode == UV_RUN_DEFAULT) { - if (r) - uv__update_time(loop); + if (mode == UV_RUN_DEFAULT && r != 0 && loop->stop_flag == 0) { + uv__update_time(loop); uv__run_timers(loop); } diff --git a/src/win/core.c b/src/win/core.c index 2ae8aa7d..e9885a0f 100644 --- a/src/win/core.c +++ b/src/win/core.c @@ -629,9 +629,8 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) { * while loop for UV_RUN_DEFAULT. Otherwise timers only need to be executed * once, which should be done after polling in order to maintain proper * execution order of the conceptual event loop. */ - if (mode == UV_RUN_DEFAULT) { - if (r) - uv_update_time(loop); + if (mode == UV_RUN_DEFAULT && r != 0 && loop->stop_flag == 0) { + uv_update_time(loop); uv__run_timers(loop); } diff --git a/test/test-list.h b/test/test-list.h index b2c88170..0d385f21 100644 --- a/test/test-list.h +++ b/test/test-list.h @@ -29,6 +29,7 @@ TEST_DECLARE (loop_alive) TEST_DECLARE (loop_close) TEST_DECLARE (loop_instant_close) TEST_DECLARE (loop_stop) +TEST_DECLARE (loop_stop_before_run) TEST_DECLARE (loop_update_time) TEST_DECLARE (loop_backend_timeout) TEST_DECLARE (loop_configure) @@ -233,6 +234,7 @@ TEST_DECLARE (timer_null_callback) TEST_DECLARE (timer_early_check) TEST_DECLARE (timer_no_double_call_once) TEST_DECLARE (timer_no_double_call_nowait) +TEST_DECLARE (timer_no_run_on_unref) TEST_DECLARE (idle_starvation) TEST_DECLARE (idle_check) TEST_DECLARE (loop_handles) @@ -573,6 +575,7 @@ TASK_LIST_START TEST_ENTRY (loop_close) TEST_ENTRY (loop_instant_close) TEST_ENTRY (loop_stop) + TEST_ENTRY (loop_stop_before_run) TEST_ENTRY (loop_update_time) TEST_ENTRY (loop_backend_timeout) TEST_ENTRY (loop_configure) @@ -846,6 +849,7 @@ TASK_LIST_START TEST_ENTRY (timer_early_check) TEST_ENTRY (timer_no_double_call_once) TEST_ENTRY (timer_no_double_call_nowait) + TEST_ENTRY (timer_no_run_on_unref) TEST_ENTRY (idle_starvation) TEST_ENTRY (idle_check) diff --git a/test/test-loop-stop.c b/test/test-loop-stop.c index 02aa12f1..981d20d1 100644 --- a/test/test-loop-stop.c +++ b/test/test-loop-stop.c @@ -70,3 +70,14 @@ TEST_IMPL(loop_stop) { MAKE_VALGRIND_HAPPY(uv_default_loop()); return 0; } + + +TEST_IMPL(loop_stop_before_run) { + ASSERT_OK(uv_timer_init(uv_default_loop(), &timer_handle)); + ASSERT_OK(uv_timer_start(&timer_handle, (uv_timer_cb) abort, 0, 0)); + uv_stop(uv_default_loop()); + ASSERT_NE(uv_run(uv_default_loop(), UV_RUN_DEFAULT), 0); + + MAKE_VALGRIND_HAPPY(uv_default_loop()); + return 0; +} diff --git a/test/test-timer.c b/test/test-timer.c index eb54bb25..2488f14c 100644 --- a/test/test-timer.c +++ b/test/test-timer.c @@ -407,3 +407,15 @@ TEST_IMPL(timer_no_double_call_nowait) { MAKE_VALGRIND_HAPPY(uv_default_loop()); return 0; } + +TEST_IMPL(timer_no_run_on_unref) { + uv_timer_t timer_handle; + + ASSERT_OK(uv_timer_init(uv_default_loop(), &timer_handle)); + ASSERT_OK(uv_timer_start(&timer_handle, (uv_timer_cb) abort, 0, 0)); + uv_unref((uv_handle_t*) &timer_handle); + ASSERT_EQ(uv_run(uv_default_loop(), UV_RUN_DEFAULT), 0); + + MAKE_VALGRIND_HAPPY(uv_default_loop()); + return 0; +}