Skip to content
This repository has been archived by the owner on May 4, 2018. It is now read-only.

Zero-delay timers are executed immediately #1427

Open
orborde opened this issue Aug 18, 2014 · 8 comments
Open

Zero-delay timers are executed immediately #1427

orborde opened this issue Aug 18, 2014 · 8 comments

Comments

@orborde
Copy link

orborde commented Aug 18, 2014

If, during a timer callback, I schedule a timer with a timeout of 0, it will get run immediately, without the uv_loop bothering to process other non-timer pending events. If, as in the attached example, my timer callback schedules another timeout=0 timer, uv_run will get stuck forever executing my callback again and again, even if I pass UV_RUN_ONCE.

Example: https://gist.github.com/orborde/fe0d6e2747a7dd725b33
Note that uv_run never returns.

EXPECTED BEHAVIOR:
The libuv event pump should keep a separate queue of newly-scheduled timer events to (possibly) be fired on the next run through the main event loop (or the next call to uv_run if UV_RUN_ONCE is specified). It should not immediately execute a newly-scheduled timer, even if it is immediately due to be fired.

Original mailing list post:
https://groups.google.com/d/msg/libuv/uaN1o4IAWW8/WHGrB-IPsY0J

@saghul
Copy link
Contributor

saghul commented Aug 19, 2014

We should queue all due timers and run the callbacks after. This is planned, alongside with a bigger refactor.

If someone wants to work on this for the current branches please leave a note here.

@recp
Copy link
Contributor

recp commented Sep 21, 2014

@saghul can we do something like this?: recp/libuv@joyent:v1.x...timers . If uv_run_mode is NOWAIT || ONCE the timer will run once.

@saghul
Copy link
Contributor

saghul commented Sep 21, 2014

I don't hink so. It would still happen when running in default mode and it adds some non-obvious exception to timers execution which would make it harder to reason about.

@recp
Copy link
Contributor

recp commented Sep 22, 2014

The uv__run_timers is calling from uv_run so other events (non-timer or timer) will wait for the processing timers. I think we can move uv__run_timers to new thread in uv_run or we can create a thread for each timer?

@saghul
Copy link
Contributor

saghul commented Sep 22, 2014

The uv__run_timers is calling from uv_run so other events (non-timer or timer) will wait for the processing timers.

No, that's not how it works. First we calculate the poll timeout by taking the nearest timer (assuming there were no other conditions affecting the timeout), the we poll for I/O, and at the begining of the next iteration we call the callbacks of the timer which are due before "now".

I think we can move uv__run_timers to new thread in uv_run or we can create a thread for each timer?

No way, timers work within the event loop thread.

Feel free to spend time on this, but this won't be a problem in the future when we switch to a dispatch-based model. In the meantime, users can use an idle handle for 0 tiemouts.

@recp
Copy link
Contributor

recp commented Sep 22, 2014

Feel free to spend time on this, but this won't be a problem in the future when we switch to a dispatch-based model.

Do you mean Apple's Grand Central Dispatch (GCD) or like this?

@txdv
Copy link
Contributor

txdv commented Sep 22, 2014

I wonder what the 'dispatch mode' is too.

@saghul
Copy link
Contributor

saghul commented Sep 22, 2014

Do you mean Apple's Grand Central Dispatch (GCD) or like this?

No. We'll queue all callbacks and then run the callback queue after polling for I/O, instead of firing callbacks at different points in time.

I'll post an RFC after 1.0.0 with The Plan (TM).

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants