Skip to content
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

Fix nexttick exception #11

Closed
wants to merge 9 commits into from

Conversation

RobinQu
Copy link

@RobinQu RobinQu commented Sep 3, 2016

Exceptions should be thrown and process shall exit if there is no listener for uncaughtException event.

I modified the way we run post �and destroy hooks after an exception happens during next tick.

@AndreasMadsen
Copy link
Owner

Good catch, but this is not the correct fix. The timing is wrong and we can't change the throw origin. Just add a check for emitter.listenerCount('uncaughtException') > 0 in the didThrow part.

@RobinQu
Copy link
Author

RobinQu commented Sep 3, 2016

I understand there should not be an explicit catch part. But the reason to invoke post and destroy hooks in uncaughtException handler is beyond me.

@AndreasMadsen
Copy link
Owner

AndreasMadsen commented Sep 3, 2016

Look at the timing test, you made the following changes:

@@ -40,7 +40,7 @@ process.once('exit', function () {
    assert.strictEqual(throwFlag, true);
    assert.deepEqual(eventOrder, [
     'init#-1 NextTickWrap', 'pre#-1',
-    'callback', 'exception',
-    'post#-1', 'destroy#-1'
+    'callback',
+    'post#-1', 'destroy#-1', 'exception'
    ]);
  });

The timing you implemented is not correct, because the exception needs to happen before post. This is a consequence of how AsyncWrap is implemented in C++: https://github.com/nodejs/node/blob/master/src/async-wrap.cc#L238

To implement this in JS I delay post and destroy to after all the users uncaughtException event handlers have fired. This was done by using .on(ce), because the EventEmitter timing is FIFO.

@RobinQu
Copy link
Author

RobinQu commented Sep 6, 2016

I made some improvements that passed the original test.

@RobinQu
Copy link
Author

RobinQu commented Sep 6, 2016

BTW. I suppose the moment the proposal changes in node-eps land in a stable release of node, async-hook should also be changed dramatically?

@AndreasMadsen
Copy link
Owner

AndreasMadsen commented Sep 6, 2016

I would like to not mess with _fatalException. If the callback thows and there is no uncaughtException handler, I would think that the process exists before the post and destroy hooks can be called, correct? In that case you don't have to do anything.

@RobinQu
Copy link
Author

RobinQu commented Sep 7, 2016

@RobinQu
Copy link
Author

RobinQu commented Sep 7, 2016

@AndreasMadsen I am stuck in a problem relating to the HTTPParser. I understand this is not a problem about async-hook.
But I hope you can share some opinions about this failing test case: RobinQu/async-zone#1

@AndreasMadsen
Copy link
Owner

AndreasMadsen commented Sep 7, 2016

I have tested it using the current AsyncWrap implementation. As expected the post and destroy hooks are not called. I think we should stick to the current behaviour.


The test case:

'use strict';

const asyncHook = require('./');
const assert = require('assert');
const fs = require('fs');

asyncHook.addHooks({
  init: function (uid, handle) {
    process._rawDebug(`init#${uid} ${handle.constructor.name}`);
  },
  pre: function (uid) {
    process._rawDebug(`pre#${uid}`);
  },
  post: function (uid, handle, didThrow) {
    process._rawDebug(`post#${uid}`);
  },
  destroy: function (uid) {
    process._rawDebug(`destroy#${uid}`);
  }
});

asyncHook.enable();

/*
process.once('uncaughtException', function () {
  process._rawDebug('exception');
});
*/

fs.access(__filename, function () {
  process._rawDebug('callback');
  throw new Error('error');
});

asyncHook.disable();

without uncaughtException:

init#1 FSReqWrap
pre#1
callback
/Users/Andreas/Sites/node_modules/async-hook/test-fsaccess-didthrow.js:31
  throw new Error('error');
  ^

Error: error
    at FSReqWrap.oncomplete (fs.js:123:15)

with uncaughtException

init#1 FSReqWrap
pre#1
callback
exception
post#1
destroy#1

@RobinQu
Copy link
Author

RobinQu commented Sep 10, 2016

I got it....

@AndreasMadsen
Copy link
Owner

Great, do you want to fix timers too?

@RobinQu
Copy link
Author

RobinQu commented Sep 12, 2016

@AndreasMadsen Ok, I will take some time to fix it.

BTW, my colleagues and I are attending Velocity conference held in NYC around Sept. 22th. I am wondering if we could meet some guys of Node.js team members in NYC.
Do you guys have some regular meetings in NYC?

@AndreasMadsen
Copy link
Owner

Thanks. I will make the final review later. Most likely I will just fix the nits myself, if that is ok.

BTW, my colleagues and I are attending Velocity conference held in NYC around Sept. 22th. I am wondering if we could meet some guys of Node.js team members in NYC.

No idea, I live in Denmark. You should should ask on Twitter and https://github.com/nodejs/diagnostics/.

@RobinQu
Copy link
Author

RobinQu commented Sep 12, 2016

OK. That's fine.

@AndreasMadsen
Copy link
Owner

Thanks. Landed in 129af3d and c452578. Additional tests in 3cc5607 and 5d7695a.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants