-
Notifications
You must be signed in to change notification settings - Fork 30k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
timers: warn on overflowed timeout duration #6956
Conversation
lib/timers.js
Outdated
@@ -317,6 +320,11 @@ exports.setTimeout = function(callback, after) { | |||
after *= 1; // coalesce to number or NaN | |||
|
|||
if (!(after >= 1 && after <= TIMEOUT_MAX)) { | |||
if (after > TIMEOUT_MAX) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not just emit a warning that the timer was invalid and converted to n
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lots of code out there that does either setTimeout(cb)
or setTimeout(cb, 0)
-- even our own tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough. That would be quite noisy.
lib/timers.js
Outdated
@@ -296,6 +296,9 @@ exports.enroll = function(item, msecs) { | |||
|
|||
// Ensure that msecs fits into signed int32 | |||
if (msecs > TIMEOUT_MAX) { | |||
process.emitWarning(`Timer duration overflow: ${msecs} does not fit into ` + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be simplified to:
process.emitWarning(`${msecs} does not fit into a 32-bit signed integer.\n` +
`Timeout duration was truncated to ${TIMEOUT_MAX}.`,
'TimerOverflowWarning');
The TimerOverflowWarning
name would be printed to the console and gives a consistent label to key off.
08222b4
to
f0fab62
Compare
Updated, PTAL. |
LGTM |
Blocked by #6937 |
Perviously there wasn't any clear indicator when you hit the overflow other than possibly unexpected behavior, and I think emitting a warning may be appropriate. PR-URL: nodejs#6956
@nodejs/collaborators Does this seem like a good idea or not? |
f0fab62
to
0367986
Compare
LGTM |
@@ -316,6 +319,11 @@ exports.setTimeout = function(callback, after) { | |||
|
|||
after *= 1; // coalesce to number or NaN | |||
|
|||
if (after > TIMEOUT_MAX) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If after
is NaN
, this condition will never be met.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NaN
is like 0
or -1
, and also coerces to 1
, right? If so, that's probably not surprising.
I'm going off the fact that the max timeout might be surprising.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NaN
won't be coerced to 1
:O
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm going off the fact that the max timeout might be surprising.
The warning will anyway show NaN does not fit...
. That would already be surprising I guess
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ohhh I get it.
@Fishrock123 IMHO, ideally, we would support > 31 bit (I actually had to write https://www.npmjs.com/package/safe-timers because of this, although I have to admit my use-case was browsers), but I'm guessing that may be a bit much to ask at this time. |
Why don't we support more than |
@trevnorris Are there any real-world use-cases for such timeouts? |
I had one where expiration time of data was driven by user input. The timer fired instantly when the timer was far in the future. |
@ronkorving Not arguing that we should warn on overflows, but thinking that we probably should not set such timers at all after the warning rather than keeping them in the event loop as they're unlikely to fire. |
I agree. If we have an upper bound we go beyond, it's better (in my use-case anyway, I can't speak for others) not to fire the timer at all. |
IIRC coercing was to match browser behavior? I think you can still have a larger timeout by manually creating one with |
Ping @Fishrock123 ... |
Wonder what @thealphanerd thinks of this. |
Let's see what citgm says. Warnings have been surprisingly breaking in the past citgm: https://ci.nodejs.org/view/Node.js-citgm/job/citgm-smoker/390/ |
LGTM. I'm not fond of this warning, I would rather fix the actual issue. IMHO we should If I made my calculations right, the max timer is between 24 and 25 days. I think this is big enough. |
Generally, not just applied to timers, in many embedded industrial applications (area where I work in) process lifetimes can be measured in years rather than days or hours. Especially if the system is controlling uninterruptable physical process. It is true, that there is a hint of bad design in such long timer timeout periods, but generally core runtime should be robust enough to support any long running, uninterrupted, or semi-mission-critical tasks; as long as code API/ABI usage is bug free and to the core spec. If core has any limitations against that, I'd consider it a serious core issue. Node.js might not be certified or ready for primetime in this business area just yet, but that shouldn't stop us from keeping that capability as a goal. |
@imyller I agree with you, we should fix it. I am just saying that keeping such a long timer going should be the responsibility of another piece of software (core or npm). I do not see this as a limitation, we can just link to that module from the docs. I am also in to internalize that module as a timers.setLongTimeout() thing. Node.js timers are optimized for something completely different: short lived timers (ence the limit). It is usually hard to optimize some for two different competing goals. I do not like the warning. Either we can fix it and support longer timers with the same perf, or we should throw, and maybe suggest to use another API or module. Processes that run uninterrupted for more than a lunar month are hard to see in modern cloud stacks. |
I don't feel good about throwing, I feel that too many applications may pass user input directly. |
c133999
to
83c7a88
Compare
ping @Fishrock123 ... status on this one? |
Unsure, do people think this is a good idea? I don't really want to do it unless a significant number of people do tbh. It could still be a good idea not to ignore though. |
I think we should do something about it. I would prefer a throw, but a warning would be ok too. |
How about we print a deprecation warning on overflow in Node.js 8.0.0 and move towards a throw in 9 or later? |
I am 👍 on that. |
I have mixed feelings about a deprecation warning for an overflow. I think it should be a normal warning, indicating overflow. We could also mention in that warning that it will throw in future releases (because we don't want to emit two warnings). |
I'd be good with a regular warning in 8.x and a throw in 9x or later. |
I'm not sure how I feel about throwing. IIRC browsers cap similarly and also do not throw and we kinda sorta follow them here. I think the best suggestion was just to uncap it. Not sure I'll get around to that though. |
How about supporting large numbers instead? I've tried to promote this before, and it didn't seem to get much traction. Still, I personally think it's valid as I really don't like (seemingly) arbitrary limits. I wrote a module to deal with large intervals, which perhaps may serve as inspiration: https://www.npmjs.com/package/safe-timers If there is a limit, I think a warning is more appropriate than a throw because the browser also won't throw. I kinda wish it did though. edit: Reading again, I think that's exactly what @Fishrock123 means by uncapping? :) Sorry for the redundancy if so. |
Yeah I think we should just aim to support large numbers. |
This isn't going to make it for 8.0.0 |
I guess this approach is not what we want anymore and instead the limit should just be removed? @Fishrock123 are you going to follow up on this? |
Given the complete lack of activity on this, I'm inclined to close. @Fishrock123 Please reopen if you disagree. |
Previously there wasn't any clear indicator when you hit the overflow other than possibly unexpected behavior, and I think emitting a warning may be appropriate. PR-URL: nodejs/node#6956
Checklist
Affected core subsystem(s)
timers
Description of change
Documentation is in @jasnell's PR at #6937
I realized there wasn't any clear indicator when you hit the overflow other than possibly unexpected behavior, and I think a warning may be appropriate.