Skip to content
This repository was archived by the owner on Feb 12, 2024. It is now read-only.

Commit 7dd4e01

Browse files
dryajovdaviddias
authored andcommitted
feat: make js-ipfs daemon stop with same SIG as go-ipfs (#1067)
* feat: pre-start throws if Adresses.Swarm is missing * feat: add SIGTERM handler for go-ipfs compatibility * fix: interupt message * test: adding for Addresses.Swarm empty * test: adding missing daemon tests * fix: exit with 0 on SIGINT & SIGTERM
1 parent bb715f9 commit 7dd4e01

File tree

3 files changed

+102
-10
lines changed

3 files changed

+102
-10
lines changed

src/cli/commands/daemon.js

+7-3
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,18 @@ module.exports = {
4040
print('Daemon is ready')
4141
})
4242

43-
process.on('SIGINT', () => {
44-
print('Received interrupt signal, shutting down..')
43+
const cleanup = () => {
44+
print(`Received interrupt signal, shutting down..`)
4545
httpAPI.stop((err) => {
4646
if (err) {
4747
throw err
4848
}
4949
process.exit(0)
5050
})
51-
})
51+
}
52+
53+
// listen for graceful termination
54+
process.on('SIGTERM', cleanup)
55+
process.on('SIGINT', cleanup)
5256
}
5357
}

src/core/components/pre-start.js

+9-7
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,17 @@ module.exports = function preStart (self) {
2222
(config, id, cb) => {
2323
self._peerInfo = new PeerInfo(id)
2424

25-
config.Addresses.Swarm.forEach((addr) => {
26-
let ma = multiaddr(addr)
25+
if (config.Addresses && config.Addresses.Swarm) {
26+
config.Addresses.Swarm.forEach((addr) => {
27+
let ma = multiaddr(addr)
2728

28-
if (ma.getPeerId()) {
29-
ma = ma.encapsulate('/ipfs/' + self._peerInfo.id.toB58String())
30-
}
29+
if (ma.getPeerId()) {
30+
ma = ma.encapsulate('/ipfs/' + self._peerInfo.id.toB58String())
31+
}
3132

32-
self._peerInfo.multiaddrs.add(ma)
33-
})
33+
self._peerInfo.multiaddrs.add(ma)
34+
})
35+
}
3436

3537
cb()
3638
}

test/cli/daemon.js

+86
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,104 @@
44
const expect = require('chai').expect
55
const clean = require('../utils/clean')
66
const ipfsCmd = require('../utils/ipfs-exec')
7+
const pull = require('pull-stream')
8+
const toPull = require('stream-to-pull-stream')
9+
const os = require('os')
10+
const fs = require('fs')
11+
const path = require('path')
12+
13+
const isWindows = os.platform() === 'win32'
14+
15+
const checkLock = (repo, cb) => {
16+
// skip on windows
17+
// https://github.com/ipfs/js-ipfsd-ctl/pull/155#issuecomment-326983530
18+
if (!isWindows) {
19+
if (fs.existsSync(path.join(repo, 'repo.lock'))) {
20+
cb(new Error('repo.lock not removed'))
21+
}
22+
if (fs.existsSync(path.join(repo, 'api'))) {
23+
cb(new Error('api file not removed'))
24+
}
25+
}
26+
cb()
27+
}
728

829
describe('daemon', () => {
930
let repoPath
1031
let ipfs
1132

33+
const killSig = (sig) => {
34+
let proc = null
35+
return ipfs('init').then(() => {
36+
proc = ipfs('daemon')
37+
return new Promise((resolve, reject) => {
38+
pull(
39+
toPull(proc.stdout),
40+
pull.collect((err, res) => {
41+
expect(err).to.not.exist()
42+
const data = res.toString()
43+
if (data.includes(`Daemon is ready`)) {
44+
if (proc.kill(sig)) {
45+
resolve()
46+
} else {
47+
reject(new Error(`Unable to ${sig} process`))
48+
}
49+
}
50+
})
51+
)
52+
53+
pull(
54+
toPull(proc.stderr),
55+
pull.collect((err, res) => {
56+
expect(err).to.not.exist()
57+
const data = res.toString()
58+
if (data.length > 0) {
59+
reject(new Error(data))
60+
}
61+
})
62+
)
63+
})
64+
})
65+
}
66+
1267
beforeEach(() => {
1368
repoPath = '/tmp/ipfs-test-not-found-' + Math.random().toString().substring(2, 8)
1469
ipfs = ipfsCmd(repoPath)
1570
})
1671

1772
afterEach(() => clean(repoPath))
1873

74+
it(`don't crash if Addresses.Swarm is empty`, function (done) {
75+
this.timeout(20000)
76+
ipfs('init').then(() => {
77+
return ipfs('config', 'Addresses', JSON.stringify({
78+
API: '/ip4/0.0.0.0/tcp/0',
79+
Gateway: '/ip4/0.0.0.0/tcp/0'
80+
}), '--json')
81+
}).then(() => {
82+
return ipfs('daemon')
83+
}).then((res) => {
84+
expect(res).to.have.string('Daemon is ready')
85+
done()
86+
}).catch((err) => {
87+
done(err)
88+
})
89+
})
90+
91+
it(`should handle SIGINT gracefully`, function (done) {
92+
this.timeout(20000)
93+
killSig('SIGINT').then(() => {
94+
checkLock(repoPath, done)
95+
}).catch(done)
96+
})
97+
98+
it(`should handle SIGTERM gracefully`, function (done) {
99+
this.timeout(20000)
100+
killSig('SIGTERM').then(() => {
101+
checkLock(repoPath, done)
102+
}).catch(done)
103+
})
104+
19105
it('gives error if user hasn\'t run init before', (done) => {
20106
const expectedError = 'no initialized ipfs repo found in ' + repoPath
21107

0 commit comments

Comments
 (0)