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 regression in signal unlisten and document current EE behaviour #687

Closed

Conversation

sam-github
Copy link
Contributor

process.removeAllListeners() doesn't work for signals. It should, and it used to, prior to 56668f5

I originally PRed a fix for this in nodejs/node-v0.x-archive#8953. That fix is a one-liner, wherein a subtle optimization in EventEmitter.removeAllListeners() is evaded by a seeming no-op process.on('removeListener', function(){}), which is pretty awful from a comprehensibility point of view.

src/node.js is simpler and more understandable if it just uses the new/remove listener events, but they are theoretically useless for this kind of use-case, since the documentation is officially weasely about whether they fire before or after the listener is actually added. see: nodejs/node-v0.x-archive#8853 and piscisaureus@ff350f7

I've never seen the new/remove listener used for any purpose other than what node itself could use it for: detecting whether there is indeed a listener for an event, and starting or stopping some processing accordingly. It should be easier to use the EE for this.

Even if you don't agree the indeterminancy in the EE API should be removed, node is free to depend on implementation details of itself, so 90a5e2b doesn't require c1d5fab. For node to assume that the EE behaves as it does seems better than my original fix/hack in sam-github@06b6e75

R=@bnoordhuis

The order of the `newListener` and `removeListener` events with respect
to the actual adding and removing from the underlying listeners array
should be deterministic. There is no compelling reason for leaving it
indeterminate. Changing the ordering is likely to result in breaking
code that was unwittingly relying on the current behaviour, and the
indeterminancy makes it impossible to use these events to determine when
the first or last listener is added for an event.
When the last signal listener is removed, the signal wrap should be
closed, restoring the default signal handling behaviour. This is done in
a (patched) process.removeListener(). However, events.removeAllListeners
has an optimization to avoid calling removeListener() if there are no
listeners for the 'removeListener' event, introduced in 56668f5. That
caused the following code to fail to terminate:

    process.stdin.resume();
    function listener() {};
    process.on('SIGINT', listener);
    process.removeAllListeners('SIGINT');
    process.kill(process.pid, 'SIGINT')

while the following will terminate:

    process.stdin.resume();
    function listener() {};
    process.on('SIGINT', listener);
    process.removeListener('SIGINT', listener);
    process.kill(process.pid, 'SIGINT')

Replace the method patching with use of the 'newListener' and
'removeListener' events, which will fire no matter which methods are
used to add or remove listeners.
@sam-github sam-github force-pushed the fix-regression-in-signal-unlisten branch from 90a5e2b to 09653fb Compare February 2, 2015 18:01
@sam-github
Copy link
Contributor Author

@bnoordhuis fixed the things you commented on, thanks, and rebased, PTAL

bnoordhuis pushed a commit that referenced this pull request Feb 2, 2015
The order of the `newListener` and `removeListener` events with respect
to the actual adding and removing from the underlying listeners array
should be deterministic. There is no compelling reason for leaving it
indeterminate. Changing the ordering is likely to result in breaking
code that was unwittingly relying on the current behaviour, and the
indeterminancy makes it impossible to use these events to determine when
the first or last listener is added for an event.

PR-URL: #687
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
bnoordhuis pushed a commit that referenced this pull request Feb 2, 2015
When the last signal listener is removed, the signal wrap should be
closed, restoring the default signal handling behaviour. This is done in
a (patched) process.removeListener(). However, events.removeAllListeners
has an optimization to avoid calling removeListener() if there are no
listeners for the 'removeListener' event, introduced in 56668f5. That
caused the following code to fail to terminate:

    process.stdin.resume();
    function listener() {};
    process.on('SIGINT', listener);
    process.removeAllListeners('SIGINT');
    process.kill(process.pid, 'SIGINT')

while the following will terminate:

    process.stdin.resume();
    function listener() {};
    process.on('SIGINT', listener);
    process.removeListener('SIGINT', listener);
    process.kill(process.pid, 'SIGINT')

Replace the method patching with use of the 'newListener' and
'removeListener' events, which will fire no matter which methods are
used to add or remove listeners.

PR-URL: #687
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
@bnoordhuis
Copy link
Member

Thanks Sam, landed in 233e333...e9eb2ec.

@bnoordhuis bnoordhuis closed this Feb 2, 2015
@sam-github sam-github deleted the fix-regression-in-signal-unlisten branch February 17, 2015 02:55
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