Skip to content

Commit fddc701

Browse files
committed
src: support diagnostics channel in the snapshot
PR-URL: #44193 Refs: #44014 Refs: #37476 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
1 parent d70aab6 commit fddc701

File tree

5 files changed

+132
-18
lines changed

5 files changed

+132
-18
lines changed

lib/internal/main/mksnapshot.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ const supportedModules = new SafeSet(new SafeArrayIterator([
4848
'constants',
4949
'crypto',
5050
// 'dgram',
51-
// 'diagnostics_channel',
51+
'diagnostics_channel',
5252
// 'dns',
5353
// 'dns/promises',
5454
// 'domain',
@@ -60,7 +60,7 @@ const supportedModules = new SafeSet(new SafeArrayIterator([
6060
// 'https',
6161
// 'inspector',
6262
// 'module',
63-
// 'net',
63+
'net',
6464
'os',
6565
'path',
6666
'path/posix',

lib/net.js

+4-16
Original file line numberDiff line numberDiff line change
@@ -131,20 +131,9 @@ const noop = () => {};
131131

132132
const kPerfHooksNetConnectContext = Symbol('kPerfHooksNetConnectContext');
133133

134-
let netClientSocketChannel;
135-
let netServerSocketChannel;
136-
function lazyChannels() {
137-
// TODO(joyeecheung): support diagnostics channels in the snapshot.
138-
// For now it is fine to create them lazily when there isn't a snapshot to
139-
// build. If users need the channels they would have to create them first
140-
// before invoking any built-ins that would publish to these channels
141-
// anyway.
142-
if (netClientSocketChannel === undefined) {
143-
const dc = require('diagnostics_channel');
144-
netClientSocketChannel = dc.channel('net.client.socket');
145-
netServerSocketChannel = dc.channel('net.server.socket');
146-
}
147-
}
134+
const dc = require('diagnostics_channel');
135+
const netClientSocketChannel = dc.channel('net.client.socket');
136+
const netServerSocketChannel = dc.channel('net.server.socket');
148137

149138
const {
150139
hasObserver,
@@ -217,7 +206,7 @@ function connect(...args) {
217206
const options = normalized[0];
218207
debug('createConnection', normalized);
219208
const socket = new Socket(options);
220-
lazyChannels();
209+
221210
if (netClientSocketChannel.hasSubscribers) {
222211
netClientSocketChannel.publish({
223212
socket,
@@ -1761,7 +1750,6 @@ function onconnection(err, clientHandle) {
17611750
socket.server = self;
17621751
socket._server = self;
17631752
self.emit('connection', socket);
1764-
lazyChannels();
17651753
if (netServerSocketChannel.hasSubscribers) {
17661754
netServerSocketChannel.publish({
17671755
socket,

test/fixtures/snapshot/server.js

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
'use strict';
2+
3+
const net = require('net');
4+
const {
5+
setDeserializeMainFunction
6+
} = require('v8').startupSnapshot;
7+
const dc = require('diagnostics_channel');
8+
9+
const echoServer = net.Server(function(connection) {
10+
connection.on('data', function(chunk) {
11+
connection.write(chunk);
12+
});
13+
connection.on('end', function() {
14+
connection.end();
15+
});
16+
});
17+
18+
const kNumChars = 256;
19+
const buffer = new Uint8Array(kNumChars);
20+
for (let i = 0; i < kNumChars; ++i) {
21+
buffer[i] = i;
22+
}
23+
24+
let recv = '';
25+
26+
echoServer.on('listening', function() {
27+
const port = this.address().port;
28+
console.log(`server port`, port);
29+
const c = net.createConnection({ host: '127.0.0.1', port });
30+
31+
c.on('data', function(chunk) {
32+
recv += chunk.toString('latin1');
33+
34+
if (recv.length === buffer.length) {
35+
c.end();
36+
}
37+
});
38+
39+
c.on('connect', function() {
40+
c.write(buffer);
41+
});
42+
43+
c.on('close', function() {
44+
console.log(`recv.length: ${recv.length}`);
45+
echoServer.close();
46+
});
47+
48+
});
49+
50+
dc.subscribe('net.server.socket', (({ socket }) => {
51+
console.log(`From server diagnostics channel:`, socket.localPort);
52+
}));
53+
54+
dc.subscribe('net.client.socket', (({ socket }) => {
55+
console.log(`From client diagnostics channel`);
56+
}));
57+
58+
setDeserializeMainFunction(() => {
59+
echoServer.listen(0);
60+
});

test/parallel/test-bootstrap-modules.js

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ const expectedModules = new Set([
4646
'Internal Binding wasm_web_api',
4747
'Internal Binding worker',
4848
'NativeModule buffer',
49+
'NativeModule diagnostics_channel',
4950
'NativeModule events',
5051
'NativeModule fs',
5152
'NativeModule internal/abort_controller',

test/parallel/test-snapshot-net.js

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
'use strict';
2+
3+
// This tests that a local TCP server can be snapshotted and the
4+
// diagnostics channels work across serialization.
5+
6+
require('../common');
7+
const assert = require('assert');
8+
const { spawnSync } = require('child_process');
9+
const tmpdir = require('../common/tmpdir');
10+
const fixtures = require('../common/fixtures');
11+
const path = require('path');
12+
const fs = require('fs');
13+
14+
tmpdir.refresh();
15+
const blobPath = path.join(tmpdir.path, 'snapshot.blob');
16+
const entry = fixtures.path('snapshot', 'server.js');
17+
{
18+
const child = spawnSync(process.execPath, [
19+
'--snapshot-blob',
20+
blobPath,
21+
'--build-snapshot',
22+
entry,
23+
], {
24+
cwd: tmpdir.path
25+
});
26+
if (child.status !== 0) {
27+
console.log(child.stderr.toString());
28+
console.log(child.stdout.toString());
29+
assert.strictEqual(child.status, 0);
30+
}
31+
const stats = fs.statSync(path.join(tmpdir.path, 'snapshot.blob'));
32+
assert(stats.isFile());
33+
}
34+
35+
{
36+
const child = spawnSync(process.execPath, [
37+
'--snapshot-blob',
38+
blobPath,
39+
], {
40+
cwd: tmpdir.path,
41+
env: {
42+
...process.env,
43+
}
44+
});
45+
46+
const stdout = child.stdout.toString().trim();
47+
console.log(`[stdout]:\n${stdout}\n`);
48+
const stderr = child.stderr.toString().trim();
49+
console.log(`[stderr]:\n${stderr}\n`);
50+
assert.strictEqual(child.status, 0);
51+
52+
const lines = stdout.split('\n');
53+
assert.strictEqual(lines.length, 4);
54+
55+
// The log should look like this:
56+
// server port ${port}
57+
// From client diagnostics channel
58+
// From server diagnostics channel: ${port}
59+
// recv.length: 256
60+
assert.match(lines[0], /server port (\d+)/);
61+
const port = lines[0].match(/server port (\d+)/)[1];
62+
assert.match(lines[1], /From client diagnostics channel/);
63+
assert.match(lines[2], new RegExp(`From server diagnostics channel: ${port}`));
64+
assert.match(lines[3], /recv\.length: 256/);
65+
}

0 commit comments

Comments
 (0)