Skip to content

[async_wrap] call destroy hooks on uv_timer_t - #13369

Merged
trevnorris merged 2 commits into
nodejs:masterfrom
trevnorris:destroy-on-uv_timer
Jun 2, 2017
Merged

[async_wrap] call destroy hooks on uv_timer_t#13369
trevnorris merged 2 commits into
nodejs:masterfrom
trevnorris:destroy-on-uv_timer

Conversation

@trevnorris

@trevnorristrevnorris commented Jun 1, 2017

Copy link
Copy Markdown
Contributor
Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • commit message follows commit guidelines
Affected core subsystem(s)

async_wrap

Summary

Calling the destroy callbacks in a uv_idle_t causes a timing issue where
if a handle or request is closed then the class isn't deleted until
uv_close() callbacks are called (which happens after the poll phase).
This results in some destroy callbacks not being called just before the
application exits. So instead switch the destroy callbacks to be called
in a uv_timer_t with the timeout set to zero.

When uv_run() is called with UV_RUN_ONCE the final operation of the
event loop is to process all remaining timers. By setting the timeout to
zero it results in the destroy callbacks being processed after
uv_close() but before uv_run() returned. Processing the destroyed ids
that were previously missed.

Also, process the destroy_ids_list() in a do {} while() loop that makes
sure the vector is empty before returning. Which also makes running
clear() unnecessary.

Fixes: #13262

@addaleax Hope you don't mind that I added the relevant test you included in #13286 (left you as the committer, but altered the commit message)

CI: https://ci.nodejs.org/job/node-test-commit/10272/

@nodejs-github-botnodejs-github-bot added async_wrap c++ Issues and PRs that require attention from people who are familiar with C++. labels Jun 1, 2017
@trevnorris
trevnorrisforce-pushed the destroy-on-uv_timer branch from 93436c1 to 87ae33bCompareJune 1, 2017 12:29

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just fyi, the test from #13353 might be better because it uses AsyncResource to trigger the destroy call, so it doesn’t rely on .close() specifics.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Ah thanks. And I can remove the setTimeout() at the bottom of the test.

Comment threadsrc/async-wrap.cc Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

will this not call the destroy hook synchronously if emitDestroy was called from within the destroy hook? We don't want that because destroy hooks should never be called synchronously.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

@AndreasMadsen It would act like a nextTick(). The current execution scope would complete before the destroy hook was called.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yeah, that came to me a few hours after I wrote that. Thanks!

@mscdexmscdex added the timers Issues and PRs related to the timers subsystem / setImmediate, setInterval, setTimeout. label Jun 1, 2017
@trevnorris
trevnorrisforce-pushed the destroy-on-uv_timer branch from 87ae33b to fe1e23eCompareJune 1, 2017 20:41

@addaleaxaddaleax left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Great, thank you a lot!

@trevnorris

Copy link
Copy Markdown
ContributorAuthor

@addaleax Thanks for pointing to the other test. Also forgot to include your test for clearImmediate().

CI: https://ci.nodejs.org/job/node-test-commit/10290/

@AndreasMadsenAndreasMadsen left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM, thanks for taking care of this.

trevnorrisand others added 2 commits June 2, 2017 16:21
Calling the destroy callbacks in a uv_idle_t causes a timing issue where
if a handle or request is closed then the class isn't deleted until
uv_close() callbacks are called (which happens after the poll phase).
This results in some destroy callbacks not being called just before the
application exits. So instead switch the destroy callbacks to be called
in a uv_timer_t with the timeout set to zero.
When uv_run() is called with UV_RUN_ONCE the final operation of the
event loop is to process all remaining timers. By setting the timeout to
zero it results in the destroy callbacks being processed after
uv_close() but before uv_run() returned. Processing the destroyed ids
that were previously missed.
Also, process the destroy_ids_list() in a do {} while() loop that makes
sure the vector is empty before returning. Which also makes running
clear() unnecessary.
Fixes: nodejs#13262
PR-URL: nodejs#13369
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Andreas Madsen <amwebdk@gmail.com>
Verify that the destroy callback for a TCP server is called before exit
if it is closed in another destroy callback.
Fixes: nodejs#13262
PR-URL: nodejs#13369
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
Reviewed-By: Andreas Madsen <amwebdk@gmail.com>
@trevnorris
trevnorrisforce-pushed the destroy-on-uv_timer branch from 5e4aaee to 78b1358CompareJune 2, 2017 22:22
@trevnorris
trevnorris merged commit 78b1358 into nodejs:masterJun 2, 2017
@trevnorris

Copy link
Copy Markdown
ContributorAuthor

Landed in 1e44fd9 and 78b1358

Thanks all!

jasnell pushed a commit that referenced this pull request Jun 5, 2017
Calling the destroy callbacks in a uv_idle_t causes a timing issue where
if a handle or request is closed then the class isn't deleted until
uv_close() callbacks are called (which happens after the poll phase).
This results in some destroy callbacks not being called just before the
application exits. So instead switch the destroy callbacks to be called
in a uv_timer_t with the timeout set to zero.
When uv_run() is called with UV_RUN_ONCE the final operation of the
event loop is to process all remaining timers. By setting the timeout to
zero it results in the destroy callbacks being processed after
uv_close() but before uv_run() returned. Processing the destroyed ids
that were previously missed.
Also, process the destroy_ids_list() in a do {} while() loop that makes
sure the vector is empty before returning. Which also makes running
clear() unnecessary.
Fixes: #13262
PR-URL: #13369
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Andreas Madsen <amwebdk@gmail.com>
jasnell pushed a commit that referenced this pull request Jun 5, 2017
Verify that the destroy callback for a TCP server is called before exit
if it is closed in another destroy callback.
Fixes: #13262
PR-URL: #13369
Reviewed-By: Trevor Norris <trev.norris@gmail.com>
Reviewed-By: Andreas Madsen <amwebdk@gmail.com>
@jasnelljasnell mentioned this pull request Jun 5, 2017
@gibfahngibfahn mentioned this pull request Jun 15, 2017
3 tasks
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c++Issues and PRs that require attention from people who are familiar with C++.timersIssues and PRs related to the timers subsystem / setImmediate, setInterval, setTimeout.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Questions: async_hooks destroy callback vs setImmediate

7 participants

@trevnorris@jasnell@AndreasMadsen@addaleax@mscdex@MylesBorins@nodejs-github-bot