Skip to content
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

Closed

Conversation

Fishrock123
Copy link
Contributor

Checklist
  • tests and code linting passes
  • a test and/or benchmark is included
  • the commit message follows commit guidelines
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.

@nodejs-github-bot nodejs-github-bot added the timers Issues and PRs related to the timers subsystem / setImmediate, setInterval, setTimeout. label May 24, 2016
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) {
Copy link
Contributor

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?

Copy link
Contributor Author

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.

Copy link
Contributor

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.

@Fishrock123 Fishrock123 added the semver-minor PRs that contain new features and should be released in the next minor version. label May 24, 2016
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 ` +
Copy link
Member

@jasnell jasnell May 25, 2016

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.

@Fishrock123 Fishrock123 force-pushed the warn-on-timeout-overflow branch from 08222b4 to f0fab62 Compare May 25, 2016 14:29
@Fishrock123
Copy link
Contributor Author

@cjihrig
Copy link
Contributor

cjihrig commented May 25, 2016

LGTM

@Fishrock123
Copy link
Contributor Author

Blocked by #6937

@Fishrock123 Fishrock123 added the blocked PRs that are blocked by other issues or PRs. label Jun 17, 2016
@Fishrock123 Fishrock123 removed the blocked PRs that are blocked by other issues or PRs. label Jun 29, 2016
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
@Fishrock123
Copy link
Contributor Author

@nodejs/collaborators Does this seem like a good idea or not?

@Fishrock123 Fishrock123 force-pushed the warn-on-timeout-overflow branch from f0fab62 to 0367986 Compare June 29, 2016 10:13
@mcollina
Copy link
Member

LGTM

@@ -316,6 +319,11 @@ exports.setTimeout = function(callback, after) {

after *= 1; // coalesce to number or NaN

if (after > TIMEOUT_MAX) {
Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor

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

Copy link
Contributor

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

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohhh I get it.

@ronkorving
Copy link
Contributor

@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.

@trevnorris
Copy link
Contributor

Why don't we support more than 2^31-1? We can at least support 2^52 if we stay away from any bitwise operators.

@RReverser
Copy link
Member

@trevnorris Are there any real-world use-cases for such timeouts?

@ronkorving
Copy link
Contributor

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.

@RReverser
Copy link
Member

@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.

@ronkorving
Copy link
Contributor

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.

@Fishrock123
Copy link
Contributor Author

IIRC coercing was to match browser behavior?

I think you can still have a larger timeout by manually creating one with enroll() and active()?

@jasnell
Copy link
Member

jasnell commented Aug 4, 2016

Ping @Fishrock123 ...

@imyller
Copy link
Member

imyller commented Sep 15, 2016

@Fishrock123
Copy link
Contributor Author

Wonder what @thealphanerd thinks of this.

@MylesBorins
Copy link
Contributor

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/

@mcollina
Copy link
Member

LGTM.

I'm not fond of this warning, I would rather fix the actual issue. IMHO we should throw if such a timer is added, but that is semver-major.

If I made my calculations right, the max timer is between 24 and 25 days. I think this is big enough.
Maintaining a data structure within core for that long period of time sounds like a design smell from my point of view.

@imyller
Copy link
Member

imyller commented Sep 19, 2016

@mcollina

Maintaining a data structure within core for that long period like a design smell

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.

@mcollina
Copy link
Member

@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.

@Fishrock123
Copy link
Contributor Author

I don't feel good about throwing, I feel that too many applications may pass user input directly.

@rvagg rvagg force-pushed the master branch 2 times, most recently from c133999 to 83c7a88 Compare October 18, 2016 17:01
@jasnell
Copy link
Member

jasnell commented Jan 6, 2017

ping @Fishrock123 ... status on this one?

@jasnell jasnell added the stalled Issues and PRs that are stalled. label Jan 6, 2017
@Fishrock123
Copy link
Contributor Author

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.

@mcollina
Copy link
Member

mcollina commented Jan 6, 2017

I think we should do something about it. I would prefer a throw, but a warning would be ok too.

@jasnell
Copy link
Member

jasnell commented Mar 1, 2017

How about we print a deprecation warning on overflow in Node.js 8.0.0 and move towards a throw in 9 or later?

@mcollina
Copy link
Member

mcollina commented Mar 1, 2017

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.

@targos targos added this to the 8.0.0 milestone Mar 1, 2017
@cjihrig
Copy link
Contributor

cjihrig commented Mar 1, 2017

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).

@jasnell
Copy link
Member

jasnell commented Mar 1, 2017

I'd be good with a regular warning in 8.x and a throw in 9x or later.

@Fishrock123
Copy link
Contributor Author

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.

@ronkorving
Copy link
Contributor

ronkorving commented Mar 2, 2017

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.

@Fishrock123
Copy link
Contributor Author

Yeah I think we should just aim to support large numbers.

@jasnell
Copy link
Member

jasnell commented May 28, 2017

This isn't going to make it for 8.0.0

@jasnell jasnell removed this from the 8.0.0 milestone May 28, 2017
@BridgeAR
Copy link
Member

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?

@jasnell
Copy link
Member

jasnell commented Sep 15, 2017

Given the complete lack of activity on this, I'm inclined to close. @Fishrock123 Please reopen if you disagree.

@jasnell jasnell closed this Sep 15, 2017
Fishrock123 added a commit to Fishrock123/ayo that referenced this pull request Sep 19, 2017
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
semver-minor PRs that contain new features and should be released in the next minor version. stalled Issues and PRs that are stalled. timers Issues and PRs related to the timers subsystem / setImmediate, setInterval, setTimeout.
Projects
None yet
Development

Successfully merging this pull request may close these issues.