| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
There was a problem hiding this comment.
idk if it's better to have this be isUnrefed?
Sorry, something went wrong.
There was a problem hiding this comment.
It probably should be isUnrefed(), but isRefed() seems a lot simpler to think about.
Sorry, something went wrong.
There was a problem hiding this comment.
I think isRefed() sounds better ("is this holding the event loop open?").
Sorry, something went wrong.
There was a problem hiding this comment.
This is not the way it's done. This has to be declared in every child class: https://github.com/nodejs/node/blob/v5.9.0/src/tcp_wrap.cc#L87
Otherwise you're setting an object property on an already constructed object.
Sorry, something went wrong.
There was a problem hiding this comment.
oh that kinda sucks, alright.
Sorry, something went wrong.
|
(does this needs tests..?) |
Sorry, something went wrong.
There was a problem hiding this comment.
Also: is it ok to return nothing of the handle is not alive?
Sorry, something went wrong.
There was a problem hiding this comment.
returning nothing == returning undefined. but the JS signature returns bool. The question this is trying to answer is "Can this handle hold open the event loop?" So if !IsAlive() means should return false.
Sorry, something went wrong.
There was a problem hiding this comment.
Noted, thanks.
Sorry, something went wrong.
There was a problem hiding this comment.
So basically this can be boiled down to:
bool refed = IsAlive(wrap) && (wrap->flags_ & kUnref) == 0;
args.GetReturnValue().Set(Boolean::New(env->isolate(), refed);
Sorry, something went wrong.
|
Yes, I think this needs tests. Ideally you'd pass tests similar to the ones in the PRs you referenced. |
Sorry, something went wrong.
|
Yes, tests are needed. |
Sorry, something went wrong.
|
Does anyone have advice on how I can make a more generic test for this rather than testing everywhere that we expose a handle? |
Sorry, something went wrong.
|
@Fishrock123 I guess you could test on C++ level (do we have C++ level tests?) and just create a handle and interact with it directly. |
Sorry, something went wrong.
|
Does it have to be a method? Is it possible to have it as a read-only property? .refed A quick test case would be worthwhile also. |
Sorry, something went wrong.
|
@jasnell I guess this makes it explicit that you cannot just set it, but I could possibly change it otherwise. |
Sorry, something went wrong.
|
@Fishrock123 ... that makes sense. The additional () isn't too difficult to type ;-). LGTM with test cases added. |
Sorry, something went wrong.
|
The implementation is incomplete. As noted in #5834 (comment) the method needs to be placed on the FunctionTemplate of the child class. This is tedious, but haven't found a better way to automate propagation of these JS methods to the C++ child classes. @bnoordhuis had an idea a while back, but can't remember what it was. Ben, you recall anything about this? The test is simple enough: const assert = require('assert');
const net = require('net');
const server = net.createServer(() => {}).listen(common.PORT);
server.unref();
assert.equal(false, server._handle.isRefed());Remember this won't cover timer cases. To make the API parallel may need to implement a JS version that can be called on the JS timer handle instances. |
Sorry, something went wrong.
|
@Fishrock123 thanks for doing this. It would also be useful for just checking what keeps a process alive at any given time. |
Sorry, something went wrong.
|
Updated with a test, some things: I realized that some _handles we expose directly extend AsyncWrap instead of HandleWrap, and this currently does not cover those. To cover those that would mean moving the c++ check into AsyncWrap I think, and I'm not sure if that is possible/acceptable. I'm not sure if it is possible to test spawn a net.Socket that uses a Pipe handle without making a child process, so I've just gone ahead and directly made a Pipe. TTY's cannot be re-refed for some reason. The method does not exist in c++, and does not work if it is added. |
Sorry, something went wrong.
Sorry, something went wrong.
|
Hmm, getting this on Windows vs2015 and vcbt2015: not ok 86 test-handle-wrap-isrefed.js # events.js:155 # throw er; // Unhandled 'error' event # ^ # # Error: read EISDIR # at exports._errnoException (util.js:893:11) # at TTY.onread (net.js:552:26) Anyone know how to fix this test for that? const assert = makeAssert('isRefed() not working on tty_wrap');
const ReadStream = require('tty').ReadStream;
const tty = new ReadStream();
assert(Object.getPrototypeOf(tty._handle).hasOwnProperty('isRefed'), true);
assert(tty._handle.isRefed(), true);
tty.unref();
assert(tty._handle.isRefed(), false); |
Sorry, something went wrong.
|
Do you need to pass a fd to the ReadStream() constructor? Once the CI is happy, LGTM. |
Sorry, something went wrong.
There was a problem hiding this comment.
This depends on some non-obvious implementation details. If the timer is unref'd then the JS object will be moved to a TimerWrap that also isn't ref'd, correct?
Sorry, something went wrong.
There was a problem hiding this comment.
See
Lines 460 to 485 in d3a7534
timer.unref() assigns a ._handle for that specific timer, and is unlikely to change in the short term.
Sorry, something went wrong.
There was a problem hiding this comment.
I realize that. What I failed to say is that a note of this should be placed in timer_wrap.cc where the method is added so future generations can immediately see why this non-obvious implementation detail actually works.
Sorry, something went wrong.
There was a problem hiding this comment.
Where exactly do you mean? Isn't the same thing for the un(ref) methods on timer_wrap?
Sorry, something went wrong.
There was a problem hiding this comment.
My point is it may be non-obvious why setTimeout(()=>{}, 100)._handle === undefined but setTimeout(()=>{}, 100).unref()._handle links to a Timer instance. So using isRefed() is conditional to the state of timer. So not having a uniform way to access that data from the public object instance could be confusing.
Sorry, something went wrong.
There was a problem hiding this comment.
Sure, but the regular timers implementation will also benefit from this. e.g.
Lines 210 to 214 in cf94929
So I'm not sure what I would say in handle_wrap
Sorry, something went wrong.
|
Ci with fd 0 for TTY: https://ci.nodejs.org/job/node-test-pull-request/2030/ |
Sorry, something went wrong.
|
@cjihrig still the same thing on those windows builds/platforms.. |
Sorry, something went wrong.
|
Crap. The only real use of tty.ReadStream I found was in src/node.js. |
Sorry, something went wrong.
|
@nodejs/lts think we can get this in the next minor LTS release? |
Sorry, something went wrong.
|
Should be possible. It's just not yet clear when that next minor LTS release will be. |
Sorry, something went wrong.
|
OK in hindsight this behavior regarding isAlive() is a huge mistake and this should not ship as is. This needs to be accurate enough for timers to use too, and currently it isn't with either the following patches: diff --git a/lib/timers.js b/lib/timers.js
index dc2506e..3a57d86 100644
--- a/lib/timers.js
+++ b/lib/timers.js
@@ -133,8 +133,6 @@ function insert(item, unrefed) {
list = new TimersList(msecs, unrefed);
L.init(list);
list._timer._list = list;
-
- if (unrefed === true) list._timer.unref();
list._timer.start(msecs, 0);
lists[msecs] = list;
@@ -149,7 +147,7 @@ function TimersList(msecs, unrefed) {
this._idleNext = null; // Create the list with the linkedlist properties to
this._idlePrev = null; // prevent any unnecessary hidden class changes.
this._timer = new TimerWrap();
- this._unrefed = unrefed;
+ if (unrefed === true) this._timer.unref();
this.msecs = msecs;
}
@@ -207,7 +205,7 @@ function listOnTimeout() {
debug('%d list empty', msecs);
assert(L.isEmpty(list));
this.close();
- if (list._unrefed === true) {
+ if (list._timer.isRefed() === false) {
delete unrefedLists[msecs];
} else {
delete refedLists[msecs];
diff --git a/lib/timers.js b/lib/timers.js
index dc2506e..cdc0d1c 100644
--- a/lib/timers.js
+++ b/lib/timers.js
@@ -133,8 +133,6 @@ function insert(item, unrefed) {
list = new TimersList(msecs, unrefed);
L.init(list);
list._timer._list = list;
-
- if (unrefed === true) list._timer.unref();
list._timer.start(msecs, 0);
lists[msecs] = list;
@@ -149,7 +147,7 @@ function TimersList(msecs, unrefed) {
this._idleNext = null; // Create the list with the linkedlist properties to
this._idlePrev = null; // prevent any unnecessary hidden class changes.
this._timer = new TimerWrap();
- this._unrefed = unrefed;
+ if (unrefed === true) this._timer.unref();
this.msecs = msecs;
}
@@ -207,10 +205,10 @@ function listOnTimeout() {
debug('%d list empty', msecs);
assert(L.isEmpty(list));
this.close();
- if (list._unrefed === true) {
- delete unrefedLists[msecs];
- } else {
+ if (list._timer.isRefed() === true) {
delete refedLists[msecs];
+ } else {
+ delete unrefedLists[msecs];
}
} |
Sorry, something went wrong.
|
So... it does work if I close after the delete (duh), but the behavior is still pretty confusing.. Will probably remove the isAlive() check. (Which can be exposed separately if necessary) |
Sorry, something went wrong.
|
@Fishrock123 you may want to chime into the v6 thread before the rc is cut if you don't think this should land |
Sorry, something went wrong.
This fixes my perceived usability issues with 7d8882b. Which, at the time of writing, has not landed in any release except v6 RCs. This should not be considered a breaking change due to that. It is useful if you have a handle, even if it has been closed, to be able to inspect whether that handle was unrefed or not. As such, this renames the method accordingly. If people need to check a handle's aliveness, that is a separate API we should consider exposing. Refs: nodejs#5834 PR-URL: nodejs#6204 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Trevor Norris <trev.norris@gmail.com>
This reverts commit 9bb5a5e. Refs: nodejs#6382 Refs: nodejs#6204 Refs: nodejs#5834
This reverts commit f938ef7. Refs: nodejs#6382 Refs: nodejs#6204 Refs: nodejs#5834
This reverts commit 7d8882b. Refs: nodejs#6382 Refs: nodejs#6204 Refs: nodejs#5834
Sorry, something went wrong.
This allows third-party tools to check whether or not a handle that can be unreferenced is unreferenced at a particular time. Notably, this should be helpful for inspection via AsyncWrap. Also, this is useful even to node's internals, particularly timers. Refs: #5828 Refs: #5827 PR-URL: #5834 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Trevor Norris <trev.norris@gmail.com>
This fixes my perceived usability issues with 7d8882b. Which, at the time of writing, has not landed in any release except v6 RCs. This should not be considered a breaking change due to that. It is useful if you have a handle, even if it has been closed, to be able to inspect whether that handle was unrefed or not. As such, this renames the method accordingly. If people need to check a handle's aliveness, that is a separate API we should consider exposing. Refs: #5834 PR-URL: #6204 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Trevor Norris <trev.norris@gmail.com>
| Back | FazBrowse Home | New Git URL |
Pull Request check-list
this change (including linting)?
Affected core subsystem(s)
handle_wrap
Description of change
Give tools a consistent way to check if a handle is unrefed that works for all of our APIs that expose handles. E.g. would be very helpful to see which handles are umrefed in @AndreasMadsen's https://github.com/AndreasMadsen/dprof
(Some APIs, like timers, do not normally expose handles and are not addressed at that level here)
Refs: #5828
Refs: #5827
R= @trevnorris
cc @thlorenz