Uh oh!
There was an error while loading. Please reload this page.
timers: fix setTimeout expiration logic - #24214
Conversation
addaleax
commented
Nov 7, 2018
/cc @nodejs/timers |
addaleax
commented
Nov 7, 2018
There was a problem hiding this comment.
Can you please add a comment here explaining this is done to avoid floating point rounding errors? It's clear in the context of this PR but less so when seen in isolation.
There was a problem hiding this comment.
Sure, but it is a little difficult to explain just a few lines for me.. I would like you to help it.
Lines 206 to 207 in af6d262
constmsecs=1.00000000000001;console.log(126+msecs);// 127.00000000000001console.log(127+msecs);// 128In this case, when start is turning to 127, floating point precison is changed. So it will be integer.
Then,
Lines 259 to 263 in af6d262
when now is 128, it will be false.
After that, listOnTimeout will be called and check the differences here.
Lines 285 to 288 in af6d262
In this time, the diff will be 1 but msecs is 1.00000000000001.
So the if state will be true and queue.percolateDown(1) will be called.
Finally, the list will be peeked and goes into an infinite loop .
I could change list.expiry > now to list.expiry >= now, but I'm afraid it may break something else.
benjamingr
commented
Nov 7, 2018
Also @suguru03 nice seeing you around, thanks for the patch and hope you stick around and collaborate some more :) If you have any questions about the collaboration process please let us know and we'll do our best to answer them. |
suguru03
commented
Nov 7, 2018
@benjamingr Thank you very much for the comment, I really appreciate it! |
Fishrock123
commented
Nov 7, 2018
Uh, floating point / decimal numbers should be rounded to an integer IIRC. Are you saying that no longer happens on Node 11? |
suguru03
commented
Nov 7, 2018
@Fishrock123 Line 228 in ab4af08 https://github.com/nodejs/node/blob/v10.13.0/lib/timers.js#L228 |
They're not. They probably should be. That's likely a better fix for this issue. (Previously this only really worked because of implicit conversion when creating handles.) Edit: not sure it's actually a better fix after thinking about it. |
There was a problem hiding this comment.
I think this can all be replaced by list.expiry = Math.max(timer._idleStart + msecs, now + 1);
There was a problem hiding this comment.
Thanks for the review!
I'll fix it 😄
I agree with @Fishrock123 that converting to integer _when would probably instead be |
suguru03
commented
Nov 10, 2018
@TimothyGu Thanks for the comment! Also, it is for fixing the bug, I think it is better to keep the current handling. |
Trott
commented
Nov 14, 2018
So, uh, should this land as-is to fix the bug and then someone can submit a PR to align more with browsers, truncate/floor instead of ceil, etc.? Or should those fixes happen here and now? My opinion: This has been quiet for 4 days, and it would be nice to get the bug fixed. So I'm inclined to land this or to suggest that anyone who thinks it should be different should get in there and change it and push a second commit to this branch. Thoughts? In the meantime, CI: https://ci.nodejs.org/job/node-test-pull-request/18608/ |
suguru03
commented
Nov 16, 2018
I rebased onto the latest master. @apapirovski If I need to change the logic on this PR, please let me know 😄 |
8a4aff1 to
f0e35ffCompareFix the timer logic to be the same as v10.30.0. Fixes: nodejs#24203
apapirovski
commented
Nov 20, 2018
@Trott this should just land as is. I'll land later today if no one else does. |
Trott
commented
Nov 25, 2018
Unfortunately, CI is locked down right now and changes have been force-pushed since the last CI run, so this will have to wait until the release on Tuesday.... |
suguru03
commented
Nov 28, 2018
@Trott Thanks for the update! |
Trott
commented
Nov 30, 2018
Trott
commented
Dec 1, 2018
Resume Build CI: https://ci.nodejs.org/job/node-test-pull-request/19104/ |
Fishrock123
left a comment
There was a problem hiding this comment.
I’ll follow up separately with the other ideal changes
Trott
commented
Dec 1, 2018
Resume Build again: https://ci.nodejs.org/job/node-test-pull-request/19113/ |
Trott
commented
Dec 1, 2018
I've taken the problematic ubuntu1804-64 host offline so hopefully we get a non-problematic one this time. Resume Build CI: https://ci.nodejs.org/job/node-test-pull-request/19119/ |
Fix the timer logic to be the same as v10.30.0. Fixes: nodejs#24203 PR-URL: nodejs#24214 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Gus Caplan <me@gus.host> Reviewed-By: Anatoli Papirovski <apapirovski@mac.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
Trott
commented
Dec 1, 2018
Landed in e9de435. Thanks for the contribution! 🎉 |
suguru03
commented
Dec 2, 2018
@Trott Thank you very much! 😄 |
Fix the timer logic to be the same as v10.30.0. Fixes: #24203 PR-URL: #24214 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Gus Caplan <me@gus.host> Reviewed-By: Anatoli Papirovski <apapirovski@mac.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
Fix the timer logic to be the same as v10.30.0. Fixes: nodejs#24203 PR-URL: nodejs#24214 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Gus Caplan <me@gus.host> Reviewed-By: Anatoli Papirovski <apapirovski@mac.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
Reverts some timers behavior back to as it was before 2930bd1 That commit introduced an unintended change which allowed non-integer timeouts to actually exist since the value is no longer converted to an integer via a TimeWrap handle directly. Even with the fix in e9de435 non-integer timeouts are still indeterministic, because libuv does not support them. This fixes the issue by emulating the old behavior: truncate the `_idleTimeout` before using it. See comments in nodejs#24214 for more background on this.
Reverts some timers behavior back to as it was before 2930bd1 That commit introduced an unintended change which allowed non-integer timeouts to actually exist since the value is no longer converted to an integer via a TimeWrap handle directly. Even with the fix in e9de435 non-integer timeouts are still indeterministic, because libuv does not support them. This fixes the issue by emulating the old behavior: truncate the `_idleTimeout` before using it. See comments in #24214 for more background on this. PR-URL: #24819 Reviewed-By: Anatoli Papirovski <apapirovski@mac.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
Reverts some timers behavior back to as it was before 2930bd1 That commit introduced an unintended change which allowed non-integer timeouts to actually exist since the value is no longer converted to an integer via a TimeWrap handle directly. Even with the fix in e9de435 non-integer timeouts are still indeterministic, because libuv does not support them. This fixes the issue by emulating the old behavior: truncate the `_idleTimeout` before using it. See comments in #24214 for more background on this. PR-URL: #24819 Reviewed-By: Anatoli Papirovski <apapirovski@mac.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
I fixed the setTimeout issue.
I changed the logic to be the same logic as
v10.30.0following the lines. https://github.com/nodejs/node/blob/v10.13.0/lib/timers.js#L240-L243Fixes: #24203
Checklist
make -j4 test(UNIX), orvcbuild test(Windows) passes