diff --git a/lib/Local.js b/lib/Local.js index 4549cdf..054fe50 100644 --- a/lib/Local.js +++ b/lib/Local.js @@ -3,11 +3,12 @@ var childProcess = require('child_process'), path = require('path'), running = require('is-running'), LocalBinary = require('./LocalBinary'), - LocalError = require('./LocalError'); - + LocalError = require('./LocalError'), + psTree = require('ps-tree'); function Local(){ this.pid = undefined; + this.isProcessRunning = false; this.retriesLeft = 5; this.key = process.env.BROWSERSTACK_ACCESS_KEY; this.logfile = path.join(process.cwd(), 'local.log'); @@ -57,56 +58,20 @@ function Local(){ callback(new LocalError(data['message']['message'])); } else { that.pid = data['pid']; + that.isProcessRunning = true; callback(); } }); - - // that.tunnel = childProcess.spawn(binaryPath, that.getBinaryArgs()); - // that.tunnel.on('exit', function(){ - // that.tunnel = undefined; - // if(that.exitCallback) that.exitCallback(); - // }); - - // that.stdout = fs.openSync(that.logfile, 'r'); - // var chunkSize = 512, - // buffer = new Buffer(81920), - // bytesRead = 0, - // error = undefined; - - // while(true){ - // var bytes = fs.readSync(that.stdout, buffer, bytesRead, chunkSize, bytesRead); - // if(bytes == 0) continue; - - // var buffRead = buffer.slice(bytesRead, bytesRead+bytes); - // bytesRead += bytes; - - // var data = buffRead.toString(); - - // if(data.match(that.errorRegex)){ - // fs.closeSync(that.stdout); - // error = data.match(that.errorRegex)[0].trim(); - // break; - // } - - // if(data.match(that.doneRegex)){ - // fs.closeSync(that.stdout); - // break; - // } - // } - - // if(error) throw new LocalError(error); - // callback(); }); }; this.isRunning = function(){ - return this.pid && running(this.pid); + return this.pid && running(this.pid) && this.isProcessRunning; }; this.stop = function (callback) { if(!this.pid) return callback(); - this.opcode = 'stop'; - this.tunnel = childProcess.execFile(this.binaryPath, this.getBinaryArgs(), function(error){ + this.killAllProcesses(function(error){ if(error) callback(new LocalError(error.toString())); callback(); }); @@ -287,6 +252,31 @@ function Local(){ } return args; }; + + this.killAllProcesses = function(callback){ + psTree(this.pid, (err, children) => { + var childPids = children.map(val => val.PID); + var killChecker = setInterval(() => { + if(childPids.length === 0) { + clearInterval(killChecker); + process.kill(this.pid); + + // This gives time to local binary to send kill signal to railsApp. + setTimeout(() => { + this.isProcessRunning = false; + callback(); + }, 2000); + } + for(var i in childPids) { + try { + process.kill(childPids[i]); + } catch(err) { + childPids.splice(i, 1); + } + } + },100); + }); + }; } module.exports = Local; diff --git a/package.json b/package.json index 7d5127c..c040242 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "browserstack-local", - "version": "1.3.3", + "version": "1.3.4", "description": "Nodejs bindings for BrowserStack Local", "engine": "^0.10.44", "main": "index.js", @@ -19,6 +19,7 @@ "dependencies": { "https-proxy-agent": "^2.2.1", "is-running": "^2.0.0", + "ps-tree": "^1.1.0", "sinon": "^1.17.6", "temp-fs": "^0.9.9" },