Skip to content

Commit

Permalink
#2061 fix process kill
Browse files Browse the repository at this point in the history
  • Loading branch information
Unitech committed Apr 1, 2016
1 parent ea68ed0 commit ef68ef5
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 27 deletions.
8 changes: 8 additions & 0 deletions examples/sigint.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

process.on('SIGINT', function() {
// Do othing for tests
});

setInterval(function() {
console.log('I\'m alive');
}, 2000);
36 changes: 11 additions & 25 deletions lib/God/Methods.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,6 @@ var cst = require('../../constants.js');
var debug = require('debug')('pm2:methods');
var os = require('os');

/**
* Kill process group in a cross platform way
* @method crossPlatformGroupKill
* @param int pid
* @param string sig
*/
function crossPlatformGroupKill(pid, sig) {
// This would have not been needed if node.js were able
// to handle group process kill on Windows (pid < -1).
if (os.platform() === 'win32') treekill(pid, sig);
else process.kill(-pid, sig);
}

/**
* Description
* @method exports
Expand Down Expand Up @@ -248,7 +235,7 @@ module.exports = function(God) {
else {
console.log('Process with pid %d still alive after %sms, sending it SIGKILL now...', pid, kill_timeout);
try {
crossPlatformGroupKill(parseInt(pid), 'SIGKILL');
treekill(pid, 'SIGKILL');
} catch(e) {
console.error('Process cannot be killed', e.message || e.stack || e);
}
Expand All @@ -271,20 +258,19 @@ module.exports = function(God) {

var mode = pm2_env.exec_mode;

try {
if(pm2_env.treekill !== true) {
if (pm2_env.treekill !== true) {
try {
process.kill(parseInt(pid), 'SIGINT');
} catch(e) {
console.error('[SimpleKill] %s pid can not be killed', pid, e.stack, e.message);
}
else {
if (mode.indexOf('cluster') === 0) {
treekill(parseInt(pid), 'SIGINT');
}
else
crossPlatformGroupKill(parseInt(pid), 'SIGINT');
}
else {
try {
treekill(pid, 'SIGINT');
} catch(e) {
console.error('[Treekill] %s pid can not be killed', pid, e.stack, e.message);
}
} catch(e) {
console.error('%s pid can not be killed', pid, e);
return cb(null, 'Cannot be killed');
}

return God.processIsDead(pid, pm2_env, cb);
Expand Down
119 changes: 117 additions & 2 deletions test/programmatic/signals.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ describe('Signal kill (+delayed)', function() {
});
});

describe('with 3000ms PM2_KILL_TIMEOUT', function() {
describe('with 3000ms PM2_KILL_TIMEOUT (environment variable)', function() {
it('should set 3000ms to PM2_KILL_TIMEOUT', function(done) {
process.env.PM2_KILL_TIMEOUT = 3000;

Expand Down Expand Up @@ -62,7 +62,7 @@ describe('Signal kill (+delayed)', function() {
});
});

describe('with 1000ms PM2_KILL_TIMEOUT', function() {
describe('with 1000ms PM2_KILL_TIMEOUT (environment variable)', function() {
it('should set 1000ms to PM2_KILL_TIMEOUT', function(done) {
process.env.PM2_KILL_TIMEOUT = 1000;

Expand Down Expand Up @@ -103,4 +103,119 @@ describe('Signal kill (+delayed)', function() {
});
});

describe('[CLUSTER MODE] with 1000ms PM2_KILL_TIMEOUT (environment variable)', function() {
it('should set 1000ms to PM2_KILL_TIMEOUT', function(done) {
process.env.PM2_KILL_TIMEOUT = 1000;

pm2.update(function() {
done();
});
});

it('should start a script', function(done) {
pm2.start({
script : './test/fixtures/signals/delayed_sigint.js',
name : 'delayed-sigint',
exec_mode : 'cluster'
}, function(err, data) {
proc1 = data[0];
should(err).be.null;
setTimeout(done, 1000);
});
});

it('should stop script after 1000ms', function(done) {
setTimeout(function() {
pm2.list(function(err, list) {
list[0].pm2_env.status.should.eql('stopping');
});
}, 500);

setTimeout(function() {
pm2.list(function(err, list) {
list[0].pm2_env.status.should.eql('stopped');
done();
});
}, 1500);

pm2.stop('delayed-sigint', function(err, app) {
//done(err);
});

});

it('should reload script', function(done) {
setTimeout(function() {
pm2.list(function(err, list) {
list[0].pm2_env.status.should.eql('online');
list[0].pm2_env.restart_time.should.eql(1);
done();
});
}, 1500);

pm2.reload('delayed-sigint', function(err, app) {
//done(err);
});

});

it('should graceful reload script', function(done) {
setTimeout(function() {
pm2.list(function(err, list) {
list[0].pm2_env.status.should.eql('online');
list[0].pm2_env.restart_time.should.eql(2);
done();
});
}, 1500);

pm2.gracefulReload('delayed-sigint', function(err, app) {
//done(err);
});

});
});

describe('with 4000ms via kill_timeout (json/cli option)', function() {
it('should set 1000ms to PM2_KILL_TIMEOUT', function(done) {
process.env.PM2_KILL_TIMEOUT = 1000;

pm2.update(function() {
done();
});
});

it('should start a script with flag kill timeout to 4000ms', function(done) {
pm2.start({
script : './test/fixtures/signals/delayed_sigint.js',
name : 'delayed-sigint',
exec_mode : 'cluster',
kill_timeout : 4000
}, function(err, data) {
proc1 = data[0];
should(err).be.null;
setTimeout(done, 1000);
});
});

it('should stop script after 4000ms (and not 1000ms)', function(done) {
setTimeout(function() {
pm2.list(function(err, list) {
list[0].pm2_env.status.should.eql('stopping');
});
}, 1500);

setTimeout(function() {
pm2.list(function(err, list) {
list[0].pm2_env.status.should.eql('stopped');
done();
});
}, 4500);

pm2.stop('delayed-sigint', function(err, app) {
//done(err);
});

});
});

});

0 comments on commit ef68ef5

Please sign in to comment.