-
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
async-wrap: always call before and after hooks #665
Conversation
This patch allows the before and after hook to be called even if the kCallInitHook flag is 0.
@@ -255,6 +255,7 @@ class Environment { | |||
inline uint32_t* fields(); | |||
inline int fields_count() const; | |||
inline bool call_init_hook(); | |||
bool enabled; |
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.
Style: at the very least, rename it to enabled_
, make it private and only accessible through a getter and setter. The getter should be const.
That said, I believe AsyncHooks is exposed to JS land. In that case, enabled
should be a new element in the fields_
array.
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 have exposed it though the fields_
array as you sugested. Is this something there should be tested? It looks like async-wrap have a different testing policy.
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 brought it up mostly because it looked incongruous. I'll defer to @trevnorris here.
I suggest R=@trevnorris. |
} | ||
|
||
inline void Environment::AsyncHooks::set_enabled(bool enabled) { | ||
fields_[kEnabled] = (uint32_t)enabled; |
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 C-style casts.
@AndreasMadsen Your implementation looks nice. Just left a few comments. :) |
@trevnorris I have now made the requested changes. |
I'm not completely sure about the |
@AndreasMadsen Actually, now that I think about it, this change is unsafe. If Do you have a use case for allowing callbacks to be run in |
Hmm, you will have to clarify a few things before I can answer that question.
what constructor are you referring too. The
from what perspective is it incomplete. The module developers?
So if I understand correctly, you are asking about what the expected behaviour is in this case: var assert = require('assert');
var asyncWrap = process.binding('async_wrap');
var asyncHooksObject = {};
asyncWrap.setupHooks(asyncHooksObject, init, before, after);
var order = [];
function init() { order.push('init ' + this.constructor.name); }
function before() { order.push('before ' + this.constructor.name); }
function after() { order.push('after ' + this.constructor.name); }
setTimeout(function () { order.push('callback'); });
process.once('exit', function () {
assert.deepEqual(order, ['before Timer', 'callback', 'after Timer']); // behaviour 1
// or
assert.deepEqual(order, ['callback']); // behaviour 2
});
asyncHooksObject[0 /* kCallInitHook */] = 1; If I understand correctly, I don't have any meaningful use case for behaviour 1. I suppose you could make a module to debug what keeps a process temporarily hanging and to avoid delay by I any case it would prefer behaviour 1 as it is easy to filter unnecessary hook calls from userland. But missing some hook calls is not fixable from userland. behaviour 2 would also mean that |
@trevnorris status? |
@@ -263,6 +265,9 @@ class Environment { | |||
enum Fields { | |||
// Set this to not zero if the init hook should be called. | |||
kCallInitHook, | |||
// Set this to not zero if async wrap should be enabled. This is | |||
// automatically set when SetupHooks is called. | |||
kEnabled, |
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 name of the field is confusing. kCallInitHook
is what "enables" init
/before
/after
to be called. This field is an override that forces before
/after
to always be called regardless of whether init
was called, correct?
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. kEnable
is what "enables" init
/ before
/ after
to be called. But init
is only called if kCallInitHook
is true.
EDIT: it was confusing before because kCallInitHook
"enabled" init
/ before
/ after
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 know you know this, but to reiterate. The point was that before
/after
don't run unless init
runs, so enabling init
implies enabling the others. I can see your confusion though, reading though the code the implicit constraint on what callbacks are called isn't apparent.
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 know you know this, but to reiterate. The point was that before/after don't run unless init runs, so enabling init implies enabling the others.
Thanks for reiterating, I actually didn't realize that. The comment in (https://github.com/iojs/io.js/blob/v1.x/src/async-wrap.cc#L39) is rather confusing then:
This only affects the init callback.
I realize now that it also says:
If the init callback was called, then the pre/post callbacks will automatically be called.
which should be read as "if and only if". Sometimes I think my math education have kills all implicit human understanding :)
In any case I find it a bit confusing, the kCallInitHook
should really just be called kEnable
then. Or is it because before
and after
callbacks can still be called after kEnable
is called?
I would propose having a kEnable
which enables (1
) or short circuit (0
) the async_wrap
stuff. Such that some or no callbacks are called.
I'm not sure how much of a performance hit a no-opt call is these days, but I guess having kCallInitHook
, kCallBeforeHook
and kCallAfterHook
flags would make sense. The flags are such that the respective callback is only called the flag is set. For instance I don't think there is any reason for me to have an after
hook in trace (L80)
The logic behind preventing the before
and after
hook calls if init
wasn't called, is then removed. I don't think this is particularly useful, it seams like it is user protection and it is easy to implement in userland.
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 think I have come to the conclusion that both behaviors are reasonable. However the kCallInitHook
name is very confusion as it suggests it only effects the init hook, while really it affects all hooks.
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.
want to change the name to kEnableHooks
?
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.
Sure. I will refactor this PR to do that and redo the tests.
I think @trevnorris fixed this in 05f4dff, so the only value this pull requests adds is:
|
As far as I can tell, after #1614 most of this PR is no longer applicable. I'm closing this, but feel free to re-open or make a new PR for the test cases. |
This patch allows the before and after hook to be called even if the
kCallInitHook flag is 0.
test/parallel/test-async-wrap-no-init-hook.js
did not pass before.test/parallel/test-async-wrap-init-hook.js
did pass before. I just added it for the sake of completeness.issue tracking: AndreasMadsen/trace#12