-
Notifications
You must be signed in to change notification settings - Fork 29.6k
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
tracking issue: passing custom async_id's to node::AsyncWrap::AsyncWrap #14209
Labels
async_hooks
Issues and PRs related to the async hooks subsystem.
timers
Issues and PRs related to the timers subsystem / setImmediate, setInterval, setTimeout.
Comments
3 tasks
mscdex
added
async_wrap
timers
Issues and PRs related to the timers subsystem / setImmediate, setInterval, setTimeout.
labels
Jul 13, 2017
/cc @Fishrock123 |
AndreasMadsen
added
the
async_hooks
Issues and PRs related to the async hooks subsystem.
label
Jul 14, 2017
To whomever wants to help us tackle this faster, I'm available on IRC and a few IM platforms. |
3 tasks
Can I work on the issue? |
@trevnorris There is no activity since last year. Do you still need someone to work on this issue? |
It has been implemented |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
async_hooks
Issues and PRs related to the async hooks subsystem.
timers
Issues and PRs related to the timers subsystem / setImmediate, setInterval, setTimeout.
Tracking issue for difficulties using the API in #14208.
Here's a bullet list of issues, and walk through to explain the logic behind each conclusion:
Timers
The exposed APIs of
active()
/enroll()
/unenroll()
creates the following issues:Arbitrary objects can be passed to all three of those. Meaning constructors that have already had an
async_id
assigned would have a conflict.async_id
and simply not assign a new one, and skip runninginit()
.Conclusion: Not possible because an object that is meant to be assigned an
async_id
hasn't had it assigned before being passed toactive()
. Thus assigning one, and firinginit()
with atype === 'Timeout'
.timers
has it's ownasync_id_symbol
separate from the one exported byprocess.binding('async_wrap')
and have the object treated as a completely separate asynchronous resource.Conclusion: Most plausible option, but still fails in a few edge cases as will be discussed.
Option [1.2] has the edge case of possibly not being able to acquire the correct
trigger_id
. For example:Though this case is simple, and the reason for the new API. What happens is the
async_id
is assigned innet.Socket()
and thatasync_id
is passed toTCPWrap
.init()
won't fire untilTCPWrap
is constructed (which in this case isn't actually until.listen()
fornet.Server()
) users will seeasync_id
s in their graphs that haven't runinit()
yet.http.OutgoingMessage()
isn't directly attached to the object that has the reference to theTCPWrap
instance, but it still has its ownsetTimeout()
method. Making it nearly impossible to pre-assign theasync_id
and then safely pass it down the object chain to reachTCPWrap
.Usage of
enroll()
is completely optional, since any object can be passed directly toactive()
, but node internals uses bothHandleWrap::Close()
and/orunenroll()
to close the resource.Conclusion: Calling
destroy()
for on the timer'sasync_id_symbol
, anactive()
object needs to check the following things:Timeout#close()
willemitDestroy()
iftimer._called === false
and if the timer hasn't beenunenroll()
'd._onTimeout()
callback has run, regardless of whether the callback threw or not. If the error is handled then it'll be called later in the event loop. If not then the process is exiting and it didn't matter anyway.Note:
timer._called
is set totrue
before the callback runs, so callingtimer.close()
during the_onTimeout()
callback that value is safe to check inTimeout#close()
.unenroll()
willemitDestroy()
if the timer hasn't been closed, and iftimer._called === false
.Note: Part of the problem here is that while you don't need to pass pass a
Timeout()
instance toactive()
orenroll()
(though you can...) it is possible to pass aTimeout()
instance tounenroll()
. Which is basically the same as passing it toclearTimeout()
.Note: This means assigning the
async_id_symbol
(thus callingemitInit()
) should happen in the call toactive
, andenroll()
should simply be seen as a helper function to add properties to the object. Butunenroll()
can callemitDestroy()
. This makes for a somewhat unintuitive API.Note: This isn't everything, but is enough to get started. Will update soon with the remainder of the known edge cases.
cc @addaleax @AndreasMadsen @refack
The text was updated successfully, but these errors were encountered: