Skip to content

Commit b749f53

Browse files
author
Stephen Belanger
committed
diagnostics_channel: fix ref counting bug when reaching zero subscribers
1 parent 56ccd59 commit b749f53

2 files changed

Lines changed: 18 additions & 5 deletions

File tree

lib/diagnostics_channel.js

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const {
55
ArrayPrototypeIndexOf,
66
ArrayPrototypePush,
77
ArrayPrototypeSplice,
8+
SafeFinalizationRegistry,
89
ObjectGetPrototypeOf,
910
ObjectSetPrototypeOf,
1011
Promise,
@@ -29,13 +30,17 @@ const { triggerUncaughtException } = internalBinding('errors');
2930

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

32-
function decRef(channel) {
33-
if (channels.get(channel.name).decRef() === 0) {
34-
channels.delete(channel.name);
35-
}
33+
// Can't delete when weakref count reaches 0 as it could increment again.
34+
// Only GC can be used as a valid time to clean up the channels map.
35+
const finalizers = new SafeFinalizationRegistry((name) => {
36+
channels.delete(name);
37+
});
38+
39+
function decRef (channel) {
40+
channels.get(channel.name).decRef();
3641
}
3742

38-
function incRef(channel) {
43+
function incRef (channel) {
3944
channels.get(channel.name).incRef();
4045
}
4146

@@ -155,6 +160,7 @@ class Channel {
155160
this.name = name;
156161

157162
channels.set(name, new WeakReference(this));
163+
finalizers.register(this, name);
158164
}
159165

160166
static [SymbolHasInstance](instance) {

test/parallel/test-diagnostics-channel-pub-sub.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,10 @@ assert.ok(!dc.unsubscribe(name, subscriber));
4242
assert.throws(() => {
4343
dc.subscribe(name, null);
4444
}, { code: 'ERR_INVALID_ARG_TYPE' });
45+
46+
// Reaching zero subscribers should not delete from the channels map as there
47+
// will be no more weakref to incRef if another subscribe happens while the
48+
// channel object itself exists.
49+
channel.subscribe(subscriber);
50+
channel.unsubscribe(subscriber);
51+
channel.subscribe(subscriber);

0 commit comments

Comments
 (0)