-
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: do not expose .unref()._handle._list #8422
timers: do not expose .unref()._handle._list #8422
Conversation
lib/timers.js
Outdated
@@ -481,6 +481,7 @@ Timeout.prototype.unref = function() { | |||
} | |||
|
|||
var handle = reuse(this); | |||
delete handle._list; |
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 thought V8 don't like deleting props prom objects, but it might be ok if it is not perf-sensitive...
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.
Under #8372 this code path is far less likely to be hit in the first place.
I doubt the overhead from a later-than-this-tick unref()
is much of a worry.
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 removing the reference to the TimersList
instance in reuse
's implementation instead?
Also, #8372 hasn't landed yet, and it's not clear whether it will land. As a result I would think that if deleting the ._list
property is more costly than setting it to null
(or doing anything else that we know might perform better), we should not do that and instead do what we know performs better.
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 removing the reference to the
TimersList
instance inreuse
's implementation instead?
Messes with some tests that check things after unenroll()
, which also uses reuse()
.
Setting it to undefined
would be faster but I figured it could be confusing that sometimes there would be a _list
property.
If that is acceptable we can switch to it though.
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 removing the reference to the TimersList instance in reuse's implementation instead?
Messes with some tests that check things after unenroll(), which also uses reuse().
Making that change (clearing the handle's reference to the TimersList
instance) makes only one test fail on master
: test/parallel/test-timers-same-timeout-wrong-list-deleted.js
. I think that test could be updated to not rely on that reference being present for unenrolled timers.
Is this what you had in mind by "Messes with some 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.
delete is known to be a heavy operation.
I thought we were also considering setting the property to null
or undefined
, isn't it still the case?
You mentioned earlier:
Setting it to undefined would be faster but I figured it could be confusing that sometimes there would be a _list property.
If that is acceptable we can switch to it though.
Having a _list
property set to null
or undefined
seems like it would be acceptable.
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.
Should we just use Symbol
s for _list
?
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.
We could, I thought those were exposable somehow too?
I still think we should unreference it in some way though so the list can be GC'd.
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.
Using a Symbol and setting the value to undefined would accomplish both goals without incurring the potential perf hit of the delete, yes? Symbols are exposable but not without extra work.
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.
or, why don't we set it to null
. we already do that for some other properties like _handle
.
cc also @misterdjules maybe? |
The idea seems reasonable, I added a couple comments regarding the implementation. |
It seems that removing the |
Theoretically but I'm willing to bet no one even knew it existed. |
Can we use https://github.com/ChALkeR/Gzemnid to look into that? I would like to err on the side of caution regardless of the results, unless the benefits of the change far outweigh the risks, however unlikely. |
cc @ChALkeR? I dunno how this would be detected, but I guess you could look for |
There is a lot of stuff on Nothing on |
c133999
to
83c7a88
Compare
@nodejs/ctc Anyone object to me merging this one as a The |
+1 |
@Fishrock123 If it's non-functional when it's exposed then I'd consider this a bug fix. Or at most a minor. Calling this a major seems like far overkill. We're removing a property that's broken right? |
@trevnorris The property exists, but it doesn't actually have any relevant functionality since it is circularly attached to a handle which is repurposed for an individual timeout. |
@indutny What's the point? This is the only spot where it is exposed to a user. |
ping @Fishrock123 ... still making progress on this? |
Ping @Fishrock123 ... |
@indutny Is there a large benefit here to using Symbols rather than just deleting it? I mean with any property symbol or not I guess we could just set it to |
a64d9fc
to
51090c4
Compare
Updated to null out the property. @indutny, @misterdjules lgty? @nodejs/ctc please take a quick look if you could since it is semver-major. |
Oops, actually new CI: https://ci.nodejs.org/job/node-test-pull-request/7021/ |
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.
The following test program:
setTimeout(function foo() {}, 1000);
setTimeout(function foo() {}, 1000).unref();
breaks with this change:
$ cat /var/tmp/test-settimeout-unref.js
setTimeout(function foo() {}, 1000);
setTimeout(function foo() {}, 1000).unref();
$ ./node /var/tmp/test-settimeout-unref.js
timers.js:541
handle._list = null;
^
TypeError: Cannot set property '_list' of null
at Timeout.unref (timers.js:541:18)
at Object.<anonymous> (/private/var/tmp/test-settimeout-unref.js:2:37)
at Module._compile (module.js:607:30)
at Object.Module._extensions..js (module.js:618:10)
at Module.load (module.js:516:32)
at tryModuleLoad (module.js:466:12)
at Function.Module._load (module.js:458:3)
at Module.runMain (module.js:643:10)
at run (bootstrap_node.js:444:7)
at startup (bootstrap_node.js:151:9)
$
and runs successfully without this change.
lib/timers.js
Outdated
@@ -538,6 +538,7 @@ Timeout.prototype.unref = function() { | |||
} | |||
|
|||
var handle = reuse(this); | |||
handle._list = null; |
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.
What happens when handle
is null
?
8847f56
to
33b213c
Compare
Updated, CI again: https://ci.nodejs.org/job/node-test-pull-request/7316/ |
@@ -0,0 +1,16 @@ | |||
'use strict'; |
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.
Does this need a license block now that #10155 landed?
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.
... No? It did not have previous attribution? (It's new?)
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.
OK, it's been a while I haven't added a file to the repository, and it seems files added in the recent past did not include a license block, so it sounds good to me!
// Check that everything works even if the handle was not re-used. | ||
setTimeout(() => {}, 1); | ||
const timer2 = setTimeout(() => {}, 1).unref(); | ||
// Note: It is unlikely that this assertion will be hit in a failure. |
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.
That comment seems to be specific to a previous version of this PR where it would throw in that case. I don't think it's relevant in the final version.
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.
Not really, the comment states if that were to fail, i.e. the conditional was removed, node will explode internally rather than triggering this assertion.
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 would "a failure" be specifically that "the conditional was removed"? This is anticipating the future, and not reflecting the current state of the code base. Without the context of what this PR looked like in an intermediate version, this comment doesn't make any sense.
I still think it's not relevant.
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 can't think of how this will change without removing handle re-use... Are you saying that a comment that either: might be useful or not matter at all would be better off not being there at all? Isn't that every comment ever?
That bit of code does primarily test that conditional though, that isn't a problem IMO. We have added plenty of test code for code coverage that would be similar.
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.
The test code itself is great, and the comment above:
// Check that everything works even if the handle was not re-used.
is both necessary and sufficient to explain why this test code is present.
On the other hand, I find the comment:
// Note: It is unlikely that this assertion will be hit in a failure.
// Instead, timers.js will likely throw a TypeError internally.
confusing and detrimental to the understanding of that test because it does not reflect the current state of the implementation. Instead it describes what could happen if the code was changed in a specific way, that is if a conditional was removed.
I don't think we want to start documenting every possible way this test could fail depending on an infinite list of possible changes, or by definition we will end up with an infinite list of comments.
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.
A few more comments about the form, otherwise I'm OK wit the nature of the changes.
@misterdjules I believe I have addressed your comments. @indutny last chance to look, I assume you are not exactly interested so I'll be dismissing your review as it was long since addressed. |
@misterdjules updated, lgty? |
Here's a CITGM run although I'd be far beyond surprised if we covered a module interacting with this in any way. https://ci.nodejs.org/view/Node.js-citgm/job/citgm-smoker/719/ |
@indutny you never responded back and this is blocked because of that. It could land otherwise so it would be nice if you could have a look. |
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.
Dismissing the review due to no response. Please take another look.
I dismissed the review of @indutny. @nodejs/tsc PTAL because of that. This should be ready to land otherwise. |
let’s land this. |
Landed in 11f7dcf |
The list is defunct at this point. I believe this to be in effect a minor defect from 3eecdf9 PR-URL: #8422 Reviewed-By: Michaël Zasso <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Julien Gilli <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: James M Snell <[email protected]>
The list is defunct at this point. I believe this to be in effect a minor defect from 3eecdf9 PR-URL: nodejs/node#8422 Reviewed-By: Michaël Zasso <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Julien Gilli <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: James M Snell <[email protected]>
The list is defunct at this point. I believe this to be in effect a minor defect from 3eecdf9 PR-URL: nodejs/node#8422 Reviewed-By: Michaël Zasso <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Julien Gilli <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: James M Snell <[email protected]>
Checklist
make -j4 test
(UNIX), orvcbuild test nosign
(Windows) passesAffected core subsystem(s)
timers
Description of change
The list is defunct at this point.
I believe this to be in effect a minor defect/oversight from
3eecdf9
Tangentially effects/related to #8372
Edit: cc @indutny?