-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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]>
- Loading branch information
Showing
1 changed file
with
47 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,28 +1,58 @@ | ||
'use strict'; | ||
const common = require('../common'); | ||
|
||
// subprocess.send() will return false if the channel has closed or when the | ||
// backlog of unsent messages exceeds a threshold that makes it unwise to send | ||
// more. Otherwise, the method returns true. | ||
|
||
const assert = require('assert'); | ||
const net = require('net'); | ||
const { fork, spawn } = require('child_process'); | ||
const fixtures = require('../common/fixtures'); | ||
|
||
const emptyFile = fixtures.path('empty.js'); | ||
// Just a script that stays alive (does not listen to `process.on('message')`). | ||
const subScript = fixtures.path('child-process-persistent.js'); | ||
|
||
{ | ||
// Test `send` return value on `fork` that opens and IPC by deafult. | ||
const n = fork(subScript); | ||
// `subprocess.send` should always return `true` for the first send. | ||
const rv = n.send({ h: 'w' }, (err) => { if (err) assert.fail(err); }); | ||
assert.strictEqual(rv, true); | ||
n.kill(); | ||
} | ||
|
||
const n = fork(emptyFile); | ||
{ | ||
// Test `send` return value on `spawn` and saturate backlog with handles. | ||
// Call `spawn` with options that open an IPC channel. | ||
const spawnOptions = { stdio: ['pipe', 'pipe', 'pipe', 'ipc'] }; | ||
const s = spawn(process.execPath, [subScript], spawnOptions); | ||
|
||
const rv = n.send({ hello: 'world' }); | ||
assert.strictEqual(rv, true); | ||
const server = net.createServer(common.mustNotCall()).listen(0, () => { | ||
const handle = server._handle; | ||
|
||
const spawnOptions = { stdio: ['pipe', 'pipe', 'pipe', 'ipc'] }; | ||
const s = spawn(process.execPath, [emptyFile], spawnOptions); | ||
let handle = null; | ||
s.on('exit', function() { | ||
handle.close(); | ||
}); | ||
// Sending a handle and not giving the tickQueue time to acknoladge should | ||
// create the internal backlog, but leave it empty. | ||
const rv1 = s.send('one', handle, (err) => { if (err) assert.fail(err); }); | ||
assert.strictEqual(rv1, true); | ||
// Since the first `send` included a handle (should be unackoladged), | ||
// we can safly queue up only one more message. | ||
const rv2 = s.send('two', (err) => { if (err) assert.fail(err); }); | ||
assert.strictEqual(rv2, true); | ||
// The backlog should now be indicate to backoff. | ||
const rv3 = s.send('three', (err) => { if (err) assert.fail(err); }); | ||
assert.strictEqual(rv3, false); | ||
const rv4 = s.send('four', (err) => { | ||
if (err) assert.fail(err); | ||
// `send` queue should have been drained. | ||
const rv5 = s.send('5', handle, (err) => { if (err) assert.fail(err); }); | ||
assert.strictEqual(rv5, true); | ||
|
||
net.createServer(common.mustNotCall()).listen(0, function() { | ||
handle = this._handle; | ||
assert.strictEqual(s.send('one', handle), true); | ||
assert.strictEqual(s.send('two', handle), true); | ||
assert.strictEqual(s.send('three'), false); | ||
assert.strictEqual(s.send('four'), false); | ||
}); | ||
// End test and cleanup. | ||
s.kill(); | ||
handle.close(); | ||
server.close(); | ||
}); | ||
assert.strictEqual(rv4, false); | ||
}); | ||
} |