Skip to content

Commit 0d78703

Browse files
committed
Tie IPC stream lifecycle to process lifecycle
Fixes #1
1 parent 0214498 commit 0d78703

7 files changed

Lines changed: 118 additions & 1 deletion

File tree

index.js

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@ module.exports = class Sidecar extends Duplex {
1515
stdio: ['pipe', 'pipe', 'pipe', 'overlapped']
1616
})
1717

18+
this._process.on('close', this._onclose.bind(this)).on('exit', this._onexit.bind(this))
19+
1820
const ipc = this._process.stdio[3]
1921

20-
this._ipc = ipc.on('end', () => ipc.end())
22+
this._ipc = ipc.on('end', this._onend.bind(this))
2123
}
2224

2325
get stdin() {
@@ -42,4 +44,22 @@ module.exports = class Sidecar extends Duplex {
4244
_write(chunk, encoding, cb) {
4345
this._ipc.write(chunk, encoding, cb)
4446
}
47+
48+
_predestroy() {
49+
this._process.kill()
50+
}
51+
52+
_onend() {
53+
this._ipc.end()
54+
55+
this.push(null)
56+
}
57+
58+
_onclose() {
59+
this.end()
60+
}
61+
62+
_onexit(code, status) {
63+
this.emit('exit', code, status)
64+
}
4565
}

lib/runtime.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,30 @@ const path = require('bare-path')
66

77
const ipc = new Pipe(3)
88

9+
ipc.on('newListener', onnewlistener).on('removeListener', onremovelistener).on('close', onclose)
10+
11+
function onnewlistener(name, fn) {
12+
if (fn === onremovelistener || fn === onclose) return
13+
14+
switch (name) {
15+
case 'close':
16+
ipc.off(name, onclose)
17+
}
18+
}
19+
20+
function onremovelistener(name, fn) {
21+
if (fn === onremovelistener || fn === onclose) return
22+
23+
switch (name) {
24+
case 'close':
25+
if (ipc.listenerCount(name) === 0) ipc.on(name, onclose)
26+
}
27+
}
28+
29+
function onclose() {
30+
Bare.exit()
31+
}
32+
933
Bare.IPC = ipc.unref()
1034

1135
const parentURL = url.pathToFileURL(os.cwd())

test.js

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,64 @@ test('basic', (t) => {
88

99
sidecar.on('data', (data) => t.is(data.toString(), 'Hello world')).write('Hello world')
1010
})
11+
12+
test('kill on destroy', (t) => {
13+
t.plan(3)
14+
15+
const sidecar = new Sidecar(require.resolve('./test/fixtures/sleep'))
16+
17+
sidecar
18+
.on('exit', (code, status) => {
19+
t.is(code, 0)
20+
t.not(status, 0)
21+
})
22+
.on('close', () => {
23+
t.pass('closed')
24+
})
25+
.destroy()
26+
})
27+
28+
test('exit on ipc close', (t) => {
29+
t.plan(3)
30+
31+
const sidecar = new Sidecar(require.resolve('./test/fixtures/ipc-close'))
32+
33+
sidecar
34+
.on('exit', (code, status) => {
35+
t.is(code, 0)
36+
t.is(status, 0)
37+
})
38+
.on('close', () => {
39+
t.pass('closed')
40+
})
41+
})
42+
43+
test('exit on ipc destroy', (t) => {
44+
t.plan(3)
45+
46+
const sidecar = new Sidecar(require.resolve('./test/fixtures/ipc-destroy'))
47+
48+
sidecar
49+
.on('exit', (code, status) => {
50+
t.is(code, 0)
51+
t.is(status, 0)
52+
})
53+
.on('close', () => {
54+
t.pass('closed')
55+
})
56+
})
57+
58+
test('uncaught throw', (t) => {
59+
t.plan(3)
60+
61+
const sidecar = new Sidecar(require.resolve('./test/fixtures/throw'))
62+
63+
sidecar
64+
.on('exit', (code, status) => {
65+
t.is(code, 0)
66+
t.not(status, 0)
67+
})
68+
.on('close', () => {
69+
t.pass('closed')
70+
})
71+
})

test/fixtures/ipc-close.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Bare.IPC.end()
2+
3+
setTimeout(() => {
4+
throw new Error('Abort')
5+
}, 60000)

test/fixtures/ipc-destroy.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Bare.IPC.destroy()
2+
3+
setTimeout(() => {
4+
throw new Error('Abort')
5+
}, 60000)

test/fixtures/sleep.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
setTimeout(() => {}, 60000)

test/fixtures/throw.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
throw new Error('Abort')

0 commit comments

Comments
 (0)