Skip to content

Commit

Permalink
Close properly the openmct child process
Browse files Browse the repository at this point in the history
- The previously returned 'ChildProcess' object was the 'npm' process.
- This only allowed killing the child process through CTRL+C input (that
  stdin string would then generate the SIGINT event which would then be
  propagated to the child processes
  npm start
     -> sh -c ". ${NVM_DIR}/nvm.sh; nvm use v14.17.0; node server.js"
         -> node server.js
- Sending a SIGQUIT, SIGTERM or SIGINT from terminal though 'kill -s...'
  to the 'npm start' process, parent of the node.js process wouldn't kill
  the later, and there was no direct way to retrieve the node.js process
  pid programmatically.
- We should retrieve the PID information directly from the child node.js
  process through an IPC channel between child and parent node.js processes.
- For this we add a 4rd stdio entry for the spawned command:
  'spawn(...,{..., stdio: ['pipe','pipe','pipe','ipc']})'.
- We send the node.js child process PID to the parent process via the created
  IPC channel.
- We have to spawn a 'sh runModule.sh' command instead of the 'npm start' as
  npm does not propagate the IPC channel either.
- The sh script 'runModule.sh' holds the same commands as the npm script used to.

Now both node.js processes can be killed through 'kill -s...' command or through
the 'CTRL+C' input.
  • Loading branch information
nunoguedelha committed Oct 13, 2021
1 parent 2d21503 commit ad02d5f
Show file tree
Hide file tree
Showing 5 changed files with 21 additions and 11 deletions.
2 changes: 1 addition & 1 deletion iCubTelemVizServer/iCubTelemVizServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ console.log(ret.message);

function handleTermination(signal) {
console.log('Received '+signal+' ...');
openMctServerHandler.stop();
openMctServerHandler.stop(signal);
const closeTelemServerPromise = new Promise(function(resolve,reject) {
telemServer.close((error) => {
if (error === undefined) {
Expand Down
22 changes: 13 additions & 9 deletions iCubTelemVizServer/openMctServerHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const path = require('path');
function OpenMctServerHandler(outputCallback) {
// Create a child process spawn for later setting the NVM version and running the server
this.childProcess = require('child_process');
this.processHandle = null;
this.processPID = undefined;
this.outputCallback = outputCallback;
this.nvmEnv = {};
}
Expand Down Expand Up @@ -50,8 +50,8 @@ OpenMctServerHandler.prototype.start = function () {
const embeddedThis = this;

// Start the process
const execPath = path.join(process.cwd(), '..', 'openmctStaticServer');
let npmStart = this.childProcess.spawn('npm', ['start'], {shell: 'bash', cwd: execPath});
const wPath = path.join(process.cwd(), '..', 'openmctStaticServer');
let npmStart = this.childProcess.spawn('sh', ['runModule.sh'], {shell: 'bash', cwd: wPath, stdio: ['pipe','pipe','pipe','ipc']});

// Set the output callbacks
npmStart.stdout.on('data', function (data) {
Expand All @@ -63,26 +63,30 @@ OpenMctServerHandler.prototype.start = function () {
npmStart.on('error', function (error) {
embeddedThis.outputCallback('[OPEN-MCT STATIC SERVER] error: ' + error.message);
});
npmStart.on('message', function (m) {
embeddedThis.outputCallback('[OPEN-MCT STATIC SERVER] ipc: ' + JSON.stringify(m));
embeddedThis.processPID = m.pid;
});
npmStart.on('close', function (code) {
embeddedThis.processHandle = null;
embeddedThis.processPID = undefined;
embeddedThis.outputCallback('[OPEN-MCT STATIC SERVER] close: ' + code);
});

this.processHandle = npmStart;
return {status: 'OK', message: 'Opem-MCT static server process started.'};
}

OpenMctServerHandler.prototype.stop = function () {
if (this.processHandle) {
this.processHandle.kill();
OpenMctServerHandler.prototype.stop = function (signal) {
if (this.isOn()) {
process.kill(this.processPID,signal);
console.log('Killing PID %d with signal %s',this.processPID,signal);
return {status: 'WRPLY', message: 'Process OpenMCT Server stopping...'};
} else {
return {status: 'WARNING', message: 'No process OpenMCT Server running...'};
}
}

OpenMctServerHandler.prototype.isOn = function () {
return (this.processHandle != null);
return (this.processPID !== undefined);
}

function spawnSynchInOpenMCTserverPath(childProcess, shellCommand, cmdArgs) {
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions openmctStaticServer/runModule.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
. ${NVM_DIR}/nvm.sh
nvm use v14.17.0
node server.js

2 changes: 2 additions & 0 deletions openmctStaticServer/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ app.use('/', staticServer);

var port = process.env.PORT || 8080

process.send({"pid": process.pid}); // Send the process PID back to the parent

vizServer = app.listen(port, function () {
console.log('iCub Telemetry Visualizer (Open MCT based) hosted at http://localhost:' + port);
});
Expand Down

0 comments on commit ad02d5f

Please sign in to comment.