-
Notifications
You must be signed in to change notification settings - Fork 30.2k
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
node,timers: fix beforeExit with unrefed timers #2795
Conversation
@@ -1500,7 +1500,7 @@ void GetActiveHandles(const FunctionCallbackInfo<Value>& args) { | |||
Local<String> owner_sym = env->owner_string(); | |||
|
|||
for (auto w : *env->handle_wrap_queue()) { | |||
if (w->persistent().IsEmpty() || (w->flags_ & HandleWrap::kUnref)) | |||
if (w->persistent().IsEmpty() /*|| (w->flags_ & HandleWrap::kUnref)*/) |
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.
Is there a reason to leave this commented out? Git keeps track of things.
If this is still wanted and something is not finished, a TODO might be reasonable here.
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.
Oops haha. About to board my plane, couldn't fix everything up yet. :P
Note: should work (should) but may not be complete/polished. ;)
|
New CI with test: https://ci.nodejs.org/job/node-test-pull-request/271/ |
4d8768b
to
737d9b6
Compare
@@ -1543,6 +1543,18 @@ void GetActiveHandles(const FunctionCallbackInfo<Value>& args) { | |||
args.GetReturnValue().Set(ary); | |||
} | |||
|
|||
bool HasUnrefedTimerHandles(Environment* env) { | |||
|
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.
nit: remove empty line.
few nits, but otherwise LGTM. |
@@ -3969,6 +3981,11 @@ static void StartNodeInstance(void* arg) { | |||
v8::platform::PumpMessageLoop(default_platform, isolate); | |||
EmitBeforeExit(env); | |||
|
|||
// We need to run an extra event loop turn to purge unrefed handles. | |||
bool unrefedTimers = HasUnrefedTimerHandles(env); | |||
if (unrefedTimers == true) |
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.
@trevnorris would it better for me to inline the HasUnrefedTimerHandles(env)
?
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.
naw. looks good as it is.
Only |
|
||
var once = 0; | ||
|
||
process.on('beforeExit', () => { |
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.
Use common.mustCall(..., 1)
, you don't need the once
variable at all.
@Fishrock123 Not including the new test, here's the current working change: diff --git a/src/node.cc b/src/node.cc
index e5a87e7..068b548 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -3966,2 +3966,3 @@ static void StartNodeInstance(void* arg) {
SealHandleScope seal(isolate);
+ uv_loop_t* const loop = env->event_loop();
bool more;
@@ -3975,2 +3976,7 @@ static void StartNodeInstance(void* arg) {
+ // We need to run an extra event loop turn to purge unrefed handles.
+ if (loop->active_handles == 0 &&
+ loop->handle_queue[0] != loop->handle_queue[1])
+ uv_run(env->event_loop(), UV_RUN_NOWAIT);
+
// Emit `beforeExit` if the loop became alive either after emitting
diff --git a/test/parallel/test-beforeexit-event.js b/test/parallel/test-beforeexit-event.js
index f3bd127..7519a87 100644
--- a/test/parallel/test-beforeexit-event.js
+++ b/test/parallel/test-beforeexit-event.js
@@ -32,3 +32,3 @@ function tryListen() {
net.createServer()
- .listen(common.PORT)
+ .listen(common.PORT, 'localhost')
.on('listening', function() { The change to |
@trevnorris I can't repo the failure on |
@Fishrock123 Sorry. I mean that the test is broken, and shouldn't be working on master. Not that it doesn't. |
Trying to use a net server here is not reasonable, instead try with a file.
Hmmm, windows is now failing my test.
|
@Fishrock123 it's possible we're depending on implementation details of libuv for that check that Windows doesn't follow. I can debug on Monday. |
It looks like If you will replace Line 130 in e3d9d25
list.unref() (Yeah, it will leak memory. We do it just for testing purposes) - the test will pass. Looking deeper into it.
|
Yeah, confirmed. |
@indutny Saul is gone until the end of November I think. Could you maybe bring it up in |
@indutny Here's a small patch: diff --git a/deps/uv/src/win/handle.c b/deps/uv/src/win/handle.c
index 72b49d9..ab83f37 100644
--- a/deps/uv/src/win/handle.c
+++ b/deps/uv/src/win/handle.c
@@ -63,6 +63,7 @@ int uv_is_active(const uv_handle_t* handle) {
!(handle->flags & UV__HANDLE_CLOSING);
}
+#include <stdio.h>
void uv_close(uv_handle_t* handle, uv_close_cb cb) {
uv_loop_t* loop = handle->loop;
@@ -97,6 +98,7 @@ void uv_close(uv_handle_t* handle, uv_close_cb cb) {
return;
case UV_TIMER:
+ fprintf(stderr, "close on UV_TIMER\n");
uv_timer_stop((uv_timer_t*)handle);
uv__handle_closing(handle);
uv_want_endgame(loop, handle);
diff --git a/deps/uv/src/win/timer.c b/deps/uv/src/win/timer.c
index 0da541a..d9d277a 100644
--- a/deps/uv/src/win/timer.c
+++ b/deps/uv/src/win/timer.c
@@ -117,10 +117,12 @@ int uv_timer_start(uv_timer_t* handle, uv_timer_cb timer_cb, uint64_t timeout,
return 0;
}
+#include <stdio.h>
int uv_timer_stop(uv_timer_t* handle) {
uv_loop_t* loop = handle->loop;
+ fprintf(stderr, "is active: %s\n", uv__is_active(handle) ? "true" : "false");
if (!uv__is_active(handle))
return 0; And what I got from it was:
Will look more into this tomorrow. |
Here is my patch: diff --git a/deps/uv/src/win/handle-inl.h b/deps/uv/src/win/handle-inl.h
index 8d0334c..aec64c6 100644
--- a/deps/uv/src/win/handle-inl.h
+++ b/deps/uv/src/win/handle-inl.h
@@ -64,10 +64,6 @@
do { \
assert(!((handle)->flags & UV__HANDLE_CLOSING)); \
\
- if (!(((handle)->flags & UV__HANDLE_ACTIVE) && \
- ((handle)->flags & UV__HANDLE_REF))) \
- uv__active_handle_add((uv_handle_t*) (handle)); \
- \
(handle)->flags |= UV__HANDLE_CLOSING; \
(handle)->flags &= ~UV__HANDLE_ACTIVE; \
} while (0)
@@ -76,7 +72,6 @@
#define uv__handle_close(handle) \
do { \
QUEUE_REMOVE(&(handle)->handle_queue); \
- uv__active_handle_rm((uv_handle_t*) (handle)); \
\
(handle)->flags |= UV_HANDLE_CLOSED; \
\ It fixes the test, but I don't know if it is correct. |
Nah, many tests fail with my patch. We really need @piscisaureus to help us figure out what is the best course of action here |
After some thinking yesterday, I'm starting to think that uv_timer_t on unix is an outlier here. Everyone else increments active handle count on The closing timer in this test - is the one from the |
Argh, I'm very wrong. |
Alright, I think I have a fix for this PR: indutny@c3df7da . What are your thoughts, @trevnorris ? |
@indutny mind explaining that fix in more detail? don't understand why simply calling to JS would require |
@trevnorris I feel like |
@trevnorris overall, it seems that we should define |
Yes, thanks! |
Attempts to fix #1264.
My first actual c++ ever, done from an airport and low on time so I'm sure it'l need cleanup, especially about the
_unrefed
bit.cc @trevnorris, @bnoordhuis