From 5691fa0146265fafa200534fa8163a85ea0b3491 Mon Sep 17 00:00:00 2001 From: Dmitriy Ryajov Date: Fri, 10 Nov 2017 19:58:10 -0800 Subject: [PATCH 1/6] feat: pre-start throws if Adresses.Swarm is missing --- src/core/components/pre-start.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/core/components/pre-start.js b/src/core/components/pre-start.js index 4534513026..32017bd4f0 100644 --- a/src/core/components/pre-start.js +++ b/src/core/components/pre-start.js @@ -22,15 +22,17 @@ module.exports = function preStart (self) { (config, id, cb) => { self._peerInfo = new PeerInfo(id) - config.Addresses.Swarm.forEach((addr) => { - let ma = multiaddr(addr) + if (config.Addresses && config.Addresses.Swarm) { + config.Addresses.Swarm.forEach((addr) => { + let ma = multiaddr(addr) - if (ma.getPeerId()) { - ma = ma.encapsulate('/ipfs/' + self._peerInfo.id.toB58String()) - } + if (ma.getPeerId()) { + ma = ma.encapsulate('/ipfs/' + self._peerInfo.id.toB58String()) + } - self._peerInfo.multiaddrs.add(ma) - }) + self._peerInfo.multiaddrs.add(ma) + }) + } cb() } From 66bc4e188c46ba733d6370520c52ce3ae3c9f9ee Mon Sep 17 00:00:00 2001 From: Dmitriy Ryajov Date: Mon, 13 Nov 2017 02:01:31 -0800 Subject: [PATCH 2/6] feat: add SIGTERM handler for go-ipfs compatibility --- src/cli/commands/daemon.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/cli/commands/daemon.js b/src/cli/commands/daemon.js index 4529e2af54..6eaf7f8c7e 100644 --- a/src/cli/commands/daemon.js +++ b/src/cli/commands/daemon.js @@ -40,14 +40,18 @@ module.exports = { print('Daemon is ready') }) - process.on('SIGINT', () => { - print('Received interrupt signal, shutting down..') + const cleanup = (code) => { + print(`Received ${code} signal, shutting down..`) httpAPI.stop((err) => { if (err) { throw err } - process.exit(0) + process.exit(code) }) - }) + } + + // listen for graceful termination + process.on('SIGTERM', cleanup) + process.on('SIGINT', cleanup) } } From 2e74c1f980643534260d41572e3b918930297a92 Mon Sep 17 00:00:00 2001 From: Dmitriy Ryajov Date: Mon, 13 Nov 2017 03:58:39 -0800 Subject: [PATCH 3/6] fix: interupt message --- src/cli/commands/daemon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cli/commands/daemon.js b/src/cli/commands/daemon.js index 6eaf7f8c7e..c0bd4fd2f2 100644 --- a/src/cli/commands/daemon.js +++ b/src/cli/commands/daemon.js @@ -41,7 +41,7 @@ module.exports = { }) const cleanup = (code) => { - print(`Received ${code} signal, shutting down..`) + print(`Received interrupt signal, shutting down..`) httpAPI.stop((err) => { if (err) { throw err From a632eaeac4e43fc6361ebb12cf75fc3f4601612f Mon Sep 17 00:00:00 2001 From: Dmitriy Ryajov Date: Mon, 13 Nov 2017 05:03:55 -0800 Subject: [PATCH 4/6] test: adding for Addresses.Swarm empty --- test/cli/daemon.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/cli/daemon.js b/test/cli/daemon.js index 265a8892cd..9002344d59 100644 --- a/test/cli/daemon.js +++ b/test/cli/daemon.js @@ -16,6 +16,22 @@ describe('daemon', () => { afterEach(() => clean(repoPath)) + it(`don't crash if Addresses.Swarm is empty`, (done) => { + ipfs('init').then(() => { + return ipfs('config', 'Addresses', JSON.stringify({ + API: ['/ipfs/QmAbc', '/ipfs/QmDef'], + Gateway: ['/ipfs/QmAbc', '/ipfs/QmDef'] + }), '--json') + }).then(() => { + return ipfs('daemon') + }).then((res) => { + expect(res).to.have.string('Daemon is ready') + done() + }).catch((err) => { + done(err) + }) + }) + it('gives error if user hasn\'t run init before', (done) => { const expectedError = 'no initialized ipfs repo found in ' + repoPath From f15e6504e56d468c2dea4b55079779123ac35973 Mon Sep 17 00:00:00 2001 From: Dmitriy Ryajov Date: Mon, 13 Nov 2017 15:44:57 -0800 Subject: [PATCH 5/6] test: adding missing daemon tests --- test/cli/daemon.js | 76 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 73 insertions(+), 3 deletions(-) diff --git a/test/cli/daemon.js b/test/cli/daemon.js index 9002344d59..adbaeb4ee2 100644 --- a/test/cli/daemon.js +++ b/test/cli/daemon.js @@ -4,11 +4,66 @@ const expect = require('chai').expect const clean = require('../utils/clean') const ipfsCmd = require('../utils/ipfs-exec') +const pull = require('pull-stream') +const toPull = require('stream-to-pull-stream') +const os = require('os') +const fs = require('fs') +const path = require('path') + +const isWindows = os.platform() === 'win32' + +const checkLock = (repo, cb) => { + // skip on windows + // https://github.com/ipfs/js-ipfsd-ctl/pull/155#issuecomment-326983530 + if (!isWindows) { + if (fs.existsSync(path.join(repo, 'repo.lock'))) { + cb(new Error('repo.lock not removed')) + } + if (fs.existsSync(path.join(repo, 'api'))) { + cb(new Error('api file not removed')) + } + } + cb() +} describe('daemon', () => { let repoPath let ipfs + const killSig = (sig) => { + let proc = null + return ipfs('init').then(() => { + proc = ipfs('daemon') + return new Promise((resolve, reject) => { + pull( + toPull(proc.stdout), + pull.collect((err, res) => { + expect(err).to.not.exist() + const data = res.toString() + if (data.includes(`Daemon is ready`)) { + if (proc.kill(sig)) { + resolve() + } else { + reject(new Error(`Unable to ${sig} process`)) + } + } + }) + ) + + pull( + toPull(proc.stderr), + pull.collect((err, res) => { + expect(err).to.not.exist() + const data = res.toString() + if (data.length > 0) { + reject(new Error(data)) + } + }) + ) + }) + }) + } + beforeEach(() => { repoPath = '/tmp/ipfs-test-not-found-' + Math.random().toString().substring(2, 8) ipfs = ipfsCmd(repoPath) @@ -16,11 +71,12 @@ describe('daemon', () => { afterEach(() => clean(repoPath)) - it(`don't crash if Addresses.Swarm is empty`, (done) => { + it(`don't crash if Addresses.Swarm is empty`, function (done) { + this.timeout(20000) ipfs('init').then(() => { return ipfs('config', 'Addresses', JSON.stringify({ - API: ['/ipfs/QmAbc', '/ipfs/QmDef'], - Gateway: ['/ipfs/QmAbc', '/ipfs/QmDef'] + API: '/ip4/0.0.0.0/tcp/0', + Gateway: '/ip4/0.0.0.0/tcp/0' }), '--json') }).then(() => { return ipfs('daemon') @@ -32,6 +88,20 @@ describe('daemon', () => { }) }) + it(`should handle SIGINT gracefully`, function (done) { + this.timeout(20000) + killSig('SIGINT').then(() => { + checkLock(repoPath, done) + }).catch(done) + }) + + it(`should handle SIGTERM gracefully`, function (done) { + this.timeout(20000) + killSig('SIGTERM').then(() => { + checkLock(repoPath, done) + }).catch(done) + }) + it('gives error if user hasn\'t run init before', (done) => { const expectedError = 'no initialized ipfs repo found in ' + repoPath From 22c8b31c9a6808803b897633234ff39ba804c1dd Mon Sep 17 00:00:00 2001 From: Dmitriy Ryajov Date: Mon, 13 Nov 2017 16:16:43 -0800 Subject: [PATCH 6/6] fix: exit with 0 on SIGINT & SIGTERM --- src/cli/commands/daemon.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cli/commands/daemon.js b/src/cli/commands/daemon.js index c0bd4fd2f2..ba9ca6ad6a 100644 --- a/src/cli/commands/daemon.js +++ b/src/cli/commands/daemon.js @@ -40,13 +40,13 @@ module.exports = { print('Daemon is ready') }) - const cleanup = (code) => { + const cleanup = () => { print(`Received interrupt signal, shutting down..`) httpAPI.stop((err) => { if (err) { throw err } - process.exit(code) + process.exit(0) }) }