Skip to content

Commit 94be2b1

Browse files
committed
test: kill subprocess only after last ACK
* Add multiple comments. * Switch to a persistent fixture for subprocess. * Assert that `send` queue is drained. PR-URL: #15186 Fixes: #15176 Reviewed-By: James M Snell <[email protected]>
1 parent 668ad44 commit 94be2b1

File tree

1 file changed

+47
-17
lines changed

1 file changed

+47
-17
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,58 @@
11
'use strict';
22
const common = require('../common');
3+
4+
// subprocess.send() will return false if the channel has closed or when the
5+
// backlog of unsent messages exceeds a threshold that makes it unwise to send
6+
// more. Otherwise, the method returns true.
7+
38
const assert = require('assert');
49
const net = require('net');
510
const { fork, spawn } = require('child_process');
611
const fixtures = require('../common/fixtures');
712

8-
const emptyFile = fixtures.path('empty.js');
13+
// Just a script that stays alive (does not listen to `process.on('message')`).
14+
const subScript = fixtures.path('child-process-persistent.js');
15+
16+
{
17+
// Test `send` return value on `fork` that opens and IPC by deafult.
18+
const n = fork(subScript);
19+
// `subprocess.send` should always return `true` for the first send.
20+
const rv = n.send({ h: 'w' }, (err) => { if (err) assert.fail(err); });
21+
assert.strictEqual(rv, true);
22+
n.kill();
23+
}
924

10-
const n = fork(emptyFile);
25+
{
26+
// Test `send` return value on `spawn` and saturate backlog with handles.
27+
// Call `spawn` with options that open an IPC channel.
28+
const spawnOptions = { stdio: ['pipe', 'pipe', 'pipe', 'ipc'] };
29+
const s = spawn(process.execPath, [subScript], spawnOptions);
1130

12-
const rv = n.send({ hello: 'world' });
13-
assert.strictEqual(rv, true);
31+
const server = net.createServer(common.mustNotCall()).listen(0, () => {
32+
const handle = server._handle;
1433

15-
const spawnOptions = { stdio: ['pipe', 'pipe', 'pipe', 'ipc'] };
16-
const s = spawn(process.execPath, [emptyFile], spawnOptions);
17-
let handle = null;
18-
s.on('exit', function() {
19-
handle.close();
20-
});
34+
// Sending a handle and not giving the tickQueue time to acknoladge should
35+
// create the internal backlog, but leave it empty.
36+
const rv1 = s.send('one', handle, (err) => { if (err) assert.fail(err); });
37+
assert.strictEqual(rv1, true);
38+
// Since the first `send` included a handle (should be unackoladged),
39+
// we can safly queue up only one more message.
40+
const rv2 = s.send('two', (err) => { if (err) assert.fail(err); });
41+
assert.strictEqual(rv2, true);
42+
// The backlog should now be indicate to backoff.
43+
const rv3 = s.send('three', (err) => { if (err) assert.fail(err); });
44+
assert.strictEqual(rv3, false);
45+
const rv4 = s.send('four', (err) => {
46+
if (err) assert.fail(err);
47+
// `send` queue should have been drained.
48+
const rv5 = s.send('5', handle, (err) => { if (err) assert.fail(err); });
49+
assert.strictEqual(rv5, true);
2150

22-
net.createServer(common.mustNotCall()).listen(0, function() {
23-
handle = this._handle;
24-
assert.strictEqual(s.send('one', handle), true);
25-
assert.strictEqual(s.send('two', handle), true);
26-
assert.strictEqual(s.send('three'), false);
27-
assert.strictEqual(s.send('four'), false);
28-
});
51+
// End test and cleanup.
52+
s.kill();
53+
handle.close();
54+
server.close();
55+
});
56+
assert.strictEqual(rv4, false);
57+
});
58+
}

0 commit comments

Comments
 (0)