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.
In
uv_run()
, timers are only run before polling, which is where the timeout is implemented. So in a singleUV_RUN_ONCE
run, it is not possible to have your callback fired because it will only be run prior to the poll in the next pass. Ifuv_run()
is modified like so, it works as expected in all 3 cases above with only oneUV_RUN_ONCE
pass: