Skip to content

Commit

Permalink
diagnostics_channel: fix ref counting bug when reaching zero subscribers
Browse files Browse the repository at this point in the history
  • Loading branch information
Stephen Belanger committed Apr 12, 2023
1 parent 56ccd59 commit b749f53
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 5 deletions.
16 changes: 11 additions & 5 deletions lib/diagnostics_channel.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const {
ArrayPrototypeIndexOf,
ArrayPrototypePush,
ArrayPrototypeSplice,
SafeFinalizationRegistry,
ObjectGetPrototypeOf,
ObjectSetPrototypeOf,
Promise,
Expand All @@ -29,13 +30,17 @@ const { triggerUncaughtException } = internalBinding('errors');

const { WeakReference } = internalBinding('util');

function decRef(channel) {
if (channels.get(channel.name).decRef() === 0) {
channels.delete(channel.name);
}
// Can't delete when weakref count reaches 0 as it could increment again.
// Only GC can be used as a valid time to clean up the channels map.
const finalizers = new SafeFinalizationRegistry((name) => {
channels.delete(name);
});

function decRef (channel) {
channels.get(channel.name).decRef();
}

function incRef(channel) {
function incRef (channel) {
channels.get(channel.name).incRef();
}

Expand Down Expand Up @@ -155,6 +160,7 @@ class Channel {
this.name = name;

channels.set(name, new WeakReference(this));
finalizers.register(this, name);
}

static [SymbolHasInstance](instance) {
Expand Down
7 changes: 7 additions & 0 deletions test/parallel/test-diagnostics-channel-pub-sub.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,10 @@ assert.ok(!dc.unsubscribe(name, subscriber));
assert.throws(() => {
dc.subscribe(name, null);
}, { code: 'ERR_INVALID_ARG_TYPE' });

// Reaching zero subscribers should not delete from the channels map as there
// will be no more weakref to incRef if another subscribe happens while the
// channel object itself exists.
channel.subscribe(subscriber);
channel.unsubscribe(subscriber);
channel.subscribe(subscriber);

0 comments on commit b749f53

Please sign in to comment.