Running with timer timeout of 50ms and simulated code execution of 1000ms:
$ ./issue5564 50 1000
000.000 main thread pre-create
000.000 main thread post-create
000.000 main cond pre-timedwait
000.000 run_cb pre-UV_RUN_ONCE 1
000.051 run_cb post-UV_RUN_ONCE 1
000.051 run_cb pre-UV_RUN_ONCE 2
000.051 timer_cb fired, cond pre-signal
000.051 main cond post-timedwait
000.051 main async pre-send
000.051 main async post-send
000.051 main thread pre-join
000.051 async_cb fired
000.051 run_cb post-UV_RUN_ONCE 2
000.051 run_cb pre-UV_RUN_DEFAULT
000.051 run_cb post-UV_RUN_DEFAULT
000.051 main thread post-join
Note that timer_cb
was not fired until the second UV_RUN_ONCE
pass.
Running with timer timeout of 1000ms and simulated code execution of 50ms:
$ ./issue5564 1000 50
000.000 main thread pre-create
000.000 main thread post-create
000.000 main cond pre-timedwait
000.000 run_cb pre-UV_RUN_ONCE 1
000.051 main cond post-timedwait
000.051 main async pre-send
000.051 main async post-send
000.051 main thread pre-join
000.051 async_cb fired
000.051 run_cb post-UV_RUN_ONCE 1
000.051 run_cb pre-UV_RUN_ONCE 2
001.001 run_cb post-UV_RUN_ONCE 2
001.001 run_cb pre-UV_RUN_DEFAULT
001.001 run_cb post-UV_RUN_DEFAULT
001.001 main thread post-join
Note that async_cb
was fired in the first UV_RUN_ONCE
pass like it should, so the second pass is unnecessary and made the program wait until the 1 second timer.
Running with a timer timeout of 0ms (code execution time does not matter):
$ ./issue5564 0 1000
000.000 main thread pre-create
000.000 main thread post-create
000.000 main cond pre-timedwait
000.000 run_cb pre-UV_RUN_ONCE 1
000.000 timer_cb fired, cond pre-signal
000.000 main cond post-timedwait
000.000 main async pre-send
000.000 main async post-send
000.000 main thread pre-join
000.000 async_cb fired
000.000 run_cb post-UV_RUN_ONCE 1
000.000 run_cb pre-UV_RUN_ONCE 2
*BLOCKED*
With a timer timeout of 0ms, timer_cb
is fired in the first UV_RUN_ONCE
, also triggering the async_cb
, causing the second UV_RUN_ONCE
pass to block forever.
A second
UV_RUN_ONCE
should not be needed and leads to broken situations in the second and third example output I gave. If I only have oneUV_RUN_ONCE
, the timer triggers it to exit, but the timer callback is never called if the timeout is > 0ms.If the I add the second
UV_RUN_ONCE
, the second pass actually calls the callback, but breaks the other situations where the async fires before the timeout.