Open RaisinTen opened 1 year ago
The server cannot be active when the snapshot is taken (e.g. it must stop listening before the snapshot is taken, and it can listen again after the snapshot is deserialized). For obvious reasons we cannot serialize system resources on the building machine and deserialize them on a potentially different machine.
I think the example in the OP might have the intention to close the server before the snapshot is taken, but it actually doesn't get rid of the handles properly and there are some leaks (if you log process._getActiveHandles()
at process exit, there are still two streams and a socket hanging around when the process shuts down)
The server cannot be active when the snapshot is taken (e.g. it must stop listening before the snapshot is taken, and it can listen again after the snapshot is deserialized).
Is it possible to delay the snapshot generation step till after x
is assigned a value / or after process._getActiveHandles()
doesn't contain any of the relevant handles? The server should get closed at that point and it's not needed to start listening again after the snapshot is deserialized.
I think there is a leak going on, so this can't be done until the actual leak is fixed. Running this with --max-old-space-size=10
and it will crash with OOM:
'use strict';
const net = require('node:net');
const v8 = require('node:v8');
let count = 0;
function run() {
const server = net.createServer((socket) => {
socket.on('data', (data) => {
server.close();
});
socket.end('hello');
}).listen(() => {
const client = net.createConnection({ port: server.address().port }, () => {
client.end('world');
});
}).on('close', () => {
if (count++ < 100000) {
setTimeout(run, 1);
} else {
console.log(v8.writeHeapSnapshot());
}
});
}
run();
If the counter is turned down a bit to e.g. 1000 so that it still has enough (well, JS) memory to spend, in the heap snapshot generated it shows that the socket is actually never reclaimed.
Version
v20.4.0
Platform
Darwin Darshans-MacBook-Pro.local 22.4.0 Darwin Kernel Version 22.4.0: Mon Mar 6 21:00:17 PST 2023; root:xnu-8796.101.5~3/RELEASE_X86_64 x86_64
Subsystem
snapshot
What steps will reproduce the bug?
Attempting to build a snapshot from this script causes a crash.
snapshot.js:
How often does it reproduce? Is there a required condition?
Always.
What is the expected behavior? Why is that the expected behavior?
No crashes.
What do you see instead?
A crash:
It originates from this check in V8 https://github.com/nodejs/node/blob/b5e16adb1d155759e7db405eead5a43cd425785d/deps/v8/src/api/api.cc#L764-L766.
Additional information
Running the script normally just records the data returned by the client:
(I was just experimenting with storing the state of various kinds of asynchronous activities during the snapshot building phase, so that the results could be used later on in the
setDeserializeMainFunction
snapshot entry point)cc @joyeecheung