Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nodejs: Send Ctrl+C to a child process on Windows

Hi I am using child_process.spwan to start a child process running a python script on Windows. The script listens on SIGINT to gracefully exits itself. But Windows does not support signals and all node did was simulating. So child_process.kill('SIGINT') on Windows is actually killing the process unconditionally (no graceful exit, python's SIGTERM/SIGINT handler not called). Also writing a ctrl+c character to stdin does not work either.

When I look into Python APIs, I got the CTRL_BREAK_EVENT and CTRL_C_EVENT that can serve the need. I am wondering if node has equivalent platform-specific APIs like these?

Related posts but not working ones: How to send control C node.js and child_processes sending crtl+c to a node.js spawned childprocess using stdin.write()?

like image 868
mingyuan-xia Avatar asked Oct 18 '16 20:10

mingyuan-xia


People also ask

How does Nodejs handle child process?

Usually, Node. js allows single-threaded, non-blocking performance but running a single thread in a CPU cannot handle increasing workload hence the child_process module can be used to spawn child processes. The child processes communicate with each other using a built-in messaging system.

Can we create child processes in node applications?

Node provides child_process module which provides ways to create child process.


1 Answers

You can use IPC messages to signal to the child that its time to stop and gracefully terminate. The below approach uses process.on('message') to listen for messages from the parent in the child process & child_process.send() to send messages from the parent to the child.

The below code has a 1 minute timeout set to exit if the child hangs or is taking to long to finish.

py-script-wrapper.js

// Handle messages sent from the Parent
process.on('message', (msg) => {
  if (msg.action === 'STOP') {
    // Execute Graceful Termination code
    process.exit(0); // Exit Process with no Errors
  }
});

Parent Process

const cp = require('child_process');
const py = cp.fork('./py-script-wrapper.js');

// On 'SIGINT'
process.on('SIGINT', () => {
  // Send a message to the python script
  py.send({ action: 'STOP' }); 

  // Now that the child process has gracefully terminated
  // exit parent process without error
  py.on('exit', (code, signal) => {
    process.exit(0);
  });

  // If the child took too long to exit
  // Kill the child, and exit with a failure code
  setTimeout(60000, () => {
    py.kill();
    process.exit(1);
  });

});
like image 176
peteb Avatar answered Oct 04 '22 08:10

peteb