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

events.once leaks signal listener #43337

Closed
breavyn opened this issue Jun 7, 2022 · 1 comment · Fixed by #43373
Closed

events.once leaks signal listener #43337

breavyn opened this issue Jun 7, 2022 · 1 comment · Fixed by #43373
Labels
confirmed-bug Issues with confirmed bugs. events Issues and PRs related to the events subsystem / EventEmitter.

Comments

@breavyn
Copy link

breavyn commented Jun 7, 2022

Version

v18.3.0

Platform

Linux

Subsystem

events

What steps will reproduce the bug?

const { EventEmitter, once } = require("events");

(async () => {
  const controller = new AbortController();
  const ee = new EventEmitter();

  setTimeout(() => {
    controller.abort();
  }, 500);

  while (true) {
    setTimeout(() => ee.emit("test"), 100);
    await once(ee, "test", { signal: controller.signal });

    console.dir(controller.signal);
  }
})();

How often does it reproduce? Is there a required condition?

No response

What is the expected behavior?

No response

What do you see instead?

The signal abort listeners do not get removed.

AbortSignal {
  [Symbol(kEvents)]: SafeMap(1) [Map] { 'abort' => { size: 1, next: [Listener] } },
  [Symbol(events.maxEventTargetListeners)]: 10,
  [Symbol(events.maxEventTargetListenersWarned)]: false,
  [Symbol(kAborted)]: false,
  [Symbol(kReason)]: undefined
}
AbortSignal {
  [Symbol(kEvents)]: SafeMap(1) [Map] { 'abort' => { size: 2, next: [Listener] } },
  [Symbol(events.maxEventTargetListeners)]: 10,
  [Symbol(events.maxEventTargetListenersWarned)]: false,
  [Symbol(kAborted)]: false,
  [Symbol(kReason)]: undefined
}
AbortSignal {
  [Symbol(kEvents)]: SafeMap(1) [Map] { 'abort' => { size: 3, next: [Listener] } },
  [Symbol(events.maxEventTargetListeners)]: 10,
  [Symbol(events.maxEventTargetListenersWarned)]: false,
  [Symbol(kAborted)]: false,
  [Symbol(kReason)]: undefined
}
AbortSignal {
  [Symbol(kEvents)]: SafeMap(1) [Map] { 'abort' => { size: 4, next: [Listener] } },
  [Symbol(events.maxEventTargetListeners)]: 10,
  [Symbol(events.maxEventTargetListenersWarned)]: false,
  [Symbol(kAborted)]: false,
  [Symbol(kReason)]: undefined
}

Additional information

When listeners are added to EventTarget's in events.on and events.once, the listener gets wrapped. As AbortSignal is an EventTarget, this means the abort listener can never be removed.

node/lib/events.js

Lines 1011 to 1013 in b631086

// EventTarget does not have `error` event semantics like Node
// EventEmitters, we do not listen to `error` events here.
emitter.addEventListener(name, (arg) => { listener(arg); }, flags);

I confirmed that the listeners do get removed correctly when simply passing the listener in directly, however, I'm unsure if this will have any other consequences hinted at by the comment.

daeyeon added a commit to daeyeon/node that referenced this issue Jun 11, 2022
Event listeners pased to un/subscribe the `abort` event are mismatched.
This removes the wrapper function in `eventTargetAgnosticAddListener()`
and directly passes the given listener to the `EventTarget`.

IMO, removing the wrapper seems harmless, and the `AbortSignal` is
seemingly the only `EventTarget` passed to this function for now.

Fixes: nodejs#43337
Refs: nodejs#33659
Refs: nodejs#34997

Signed-off-by: Daeyeon Jeong [email protected]
daeyeon added a commit to daeyeon/node that referenced this issue Jun 11, 2022
Event listeners passed to un/subscribe the abort event are mismatched.
This removes the wrapper function in `eventTargetAgnosticAddListener()`
and directly passes the given listener to the `EventTarget`.

IMO, removing the wrapper seems harmless, and the `AbortSignal` is
seemingly the only `EventTarget` passed to this function for now.

Fixes: nodejs#43337
Refs: nodejs#33659
Refs: nodejs#34997

Signed-off-by: Daeyeon Jeong [email protected]
@daeyeon
Copy link
Member

daeyeon commented Jun 11, 2022

IMO, it's possible to directly pass the listener. Sent a PR for this. :-)

@F3n67u F3n67u added events Issues and PRs related to the events subsystem / EventEmitter. code-and-learn Issues related to the Code-and-Learn events and PRs submitted during the events. confirmed-bug Issues with confirmed bugs. and removed code-and-learn Issues related to the Code-and-Learn events and PRs submitted during the events. labels Jun 11, 2022
nodejs-github-bot pushed a commit that referenced this issue Jun 14, 2022
Event listeners passed to un/subscribe the abort event are mismatched.
This removes the wrapper function in `eventTargetAgnosticAddListener()`
and directly passes the given listener to the `EventTarget`.

IMO, removing the wrapper seems harmless, and the `AbortSignal` is
seemingly the only `EventTarget` passed to this function for now.

Fixes: #43337
Refs: #33659
Refs: #34997

Signed-off-by: Daeyeon Jeong [email protected]

PR-URL: #43373
Reviewed-By: Luigi Pinca <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Benjamin Gruenbaum <[email protected]>
danielleadams pushed a commit that referenced this issue Jun 16, 2022
Event listeners passed to un/subscribe the abort event are mismatched.
This removes the wrapper function in `eventTargetAgnosticAddListener()`
and directly passes the given listener to the `EventTarget`.

IMO, removing the wrapper seems harmless, and the `AbortSignal` is
seemingly the only `EventTarget` passed to this function for now.

Fixes: #43337
Refs: #33659
Refs: #34997

Signed-off-by: Daeyeon Jeong [email protected]

PR-URL: #43373
Reviewed-By: Luigi Pinca <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Benjamin Gruenbaum <[email protected]>
targos pushed a commit that referenced this issue Jul 12, 2022
Event listeners passed to un/subscribe the abort event are mismatched.
This removes the wrapper function in `eventTargetAgnosticAddListener()`
and directly passes the given listener to the `EventTarget`.

IMO, removing the wrapper seems harmless, and the `AbortSignal` is
seemingly the only `EventTarget` passed to this function for now.

Fixes: #43337
Refs: #33659
Refs: #34997

Signed-off-by: Daeyeon Jeong [email protected]

PR-URL: #43373
Reviewed-By: Luigi Pinca <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Benjamin Gruenbaum <[email protected]>
targos pushed a commit that referenced this issue Jul 31, 2022
Event listeners passed to un/subscribe the abort event are mismatched.
This removes the wrapper function in `eventTargetAgnosticAddListener()`
and directly passes the given listener to the `EventTarget`.

IMO, removing the wrapper seems harmless, and the `AbortSignal` is
seemingly the only `EventTarget` passed to this function for now.

Fixes: #43337
Refs: #33659
Refs: #34997

Signed-off-by: Daeyeon Jeong [email protected]

PR-URL: #43373
Reviewed-By: Luigi Pinca <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Benjamin Gruenbaum <[email protected]>
guangwong pushed a commit to noslate-project/node that referenced this issue Oct 10, 2022
Event listeners passed to un/subscribe the abort event are mismatched.
This removes the wrapper function in `eventTargetAgnosticAddListener()`
and directly passes the given listener to the `EventTarget`.

IMO, removing the wrapper seems harmless, and the `AbortSignal` is
seemingly the only `EventTarget` passed to this function for now.

Fixes: nodejs/node#43337
Refs: nodejs/node#33659
Refs: nodejs/node#34997

Signed-off-by: Daeyeon Jeong [email protected]

PR-URL: nodejs/node#43373
Reviewed-By: Luigi Pinca <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
confirmed-bug Issues with confirmed bugs. events Issues and PRs related to the events subsystem / EventEmitter.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants