Skip to content

Commit 897932c

Browse files
authored
diagnostics_channel: fix race condition with diagnostics_channel and GC
PR-URL: #59910 Reviewed-By: Stephen Belanger <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]> Reviewed-By: Gerhard Stöbich <[email protected]>
1 parent c7b0dfb commit 897932c

File tree

4 files changed

+52
-2
lines changed

4 files changed

+52
-2
lines changed

lib/diagnostics_channel.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ const { WeakReference } = require('internal/util');
3737
// Only GC can be used as a valid time to clean up the channels map.
3838
class WeakRefMap extends SafeMap {
3939
#finalizers = new SafeFinalizationRegistry((key) => {
40-
this.delete(key);
40+
// Check that the key doesn't have any value before deleting, as the WeakRef for the key
41+
// may have been replaced since finalization callbacks aren't synchronous with GC.
42+
if (!this.has(key)) this.delete(key);
4143
});
4244

4345
set(key, value) {
@@ -49,6 +51,10 @@ class WeakRefMap extends SafeMap {
4951
return super.get(key)?.get();
5052
}
5153

54+
has(key) {
55+
return !!this.get(key);
56+
}
57+
5258
incRef(key) {
5359
return super.get(key)?.incRef();
5460
}

test/fixtures/source-map/output/source_map_assert_source_line.snapshot

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value:
77
*
88
*
99
*
10-
at TracingChannel.traceSync (node:diagnostics_channel:322:14)
10+
at TracingChannel.traceSync (node:diagnostics_channel:328:14)
1111
*
1212
*
1313
*
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Flags: --expose-gc
2+
'use strict';
3+
4+
require('../common');
5+
const assert = require('assert');
6+
const { channel } = require('diagnostics_channel');
7+
8+
function test() {
9+
function subscribe() {
10+
channel('test-gc').subscribe(function noop() {});
11+
}
12+
13+
subscribe();
14+
15+
setTimeout(() => {
16+
global.gc();
17+
assert.ok(channel('test-gc').hasSubscribers, 'Channel must have subscribers');
18+
});
19+
}
20+
21+
test();
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Flags: --expose-gc
2+
'use strict';
3+
4+
require('../common');
5+
const assert = require('assert');
6+
const { channel } = require('diagnostics_channel');
7+
8+
function test() {
9+
const testChannel = channel('test-gc');
10+
11+
setTimeout(() => {
12+
const testChannel2 = channel('test-gc');
13+
14+
assert.ok(testChannel === testChannel2, 'Channel instances must be the same');
15+
});
16+
}
17+
18+
test();
19+
20+
setTimeout(() => {
21+
global.gc();
22+
test();
23+
}, 10);

0 commit comments

Comments
 (0)