How to Prevent a Node.js 12 worker Thread from terminating immediately?

by Patrick Hund   Last Updated October 20, 2019 05:26 AM

I have a Node.js application running an Express server and a worker thread that does something at regular intervals.

When the server is stopped, I need to clean up a connection to an external system that is opened by the worker thread when it starts.

I tried to add a handler on the process for SIGTERM and SIGINT signals, but this does not work, the handler function in the worker thread is not called, it exits immediately with exit code 1 when the parent process receives a SIGINT or SIGTERM, although the parent process also has a handler for these which does get called.

Here is a simple code example to reproduce the problem:

start.js

const http = require("http");
const express = require("express");
const path = require("path");
const { Worker } = require("worker_threads");

let myWorker = null;

process.on("SIGTERM", stop);
process.on("SIGINT", stop);

const app = express();
const server = http.Server(app);

myWorker = new Worker(path.join(__dirname, "./worker.js"));

myWorker.on("exit", code => console.info(`Worker exited with code ${code}`));

server.listen(3000);

function stop() {
  console.log("Main process: stop()");
  process.exit(0);
}

worker.js

process.on("SIGTERM", stop);
process.on("SIGINT", stop);

setInterval(() => console.log("beep"), 1000);

function stop() {
  console.log("Worker process: stop()");
  process.exit(0);
}

When I start soWorker.js, I get this output on the console when I interrupt the process with CTRL+C:

╰─➤  node start.js
beep
beep
beep
^CMain process: stop()
Worker exited with code 1

What I expect to happen is this:

╰─➤  node start.js
beep
beep
beep
^CMain process: stop()
Worker process: stop()
Worker exited with code 0

I expect the stop function in the worker thread to be called, so that I can use it to close the connection to the external system, then gracefully exit the worker thread process with return code 0.

Instead, the worker thread exits with code 1, which is the default when a worker thread is stopped.

My question:

How can I execute some clean-up code in my worker thread when the main process is terminated?

Am I on the right track with the approach described above?



Answers 2


I'm mostly spitballin' here, but I think this'll put you on the right track:

add to start.js

process.on('SIGTERM', cleanup);
process.on('SIGINT', cleanup);
myWorker.once('exit', stop);

function cleanup() {
  myWorker.postMessage('cleanup');
}

worker.js

const { parentPort } = require('worker_threads');

parentPort.on('message', (value) => {
  if (value === 'cleanup') {
    cleanup();
    //then process.exit(0);
  }
});

EddieDean
EddieDean
October 18, 2019 18:03 PM

The following solution should work-

  • Subscribe to main thread message event in the worker thread
  • Subscribe to SIGTERM (or whatever) in the main thread
  • When you catch the signal in the main thread, send a message to the worker thread, requesting it to clean up and exit. ** Do not exit from the main thread yet**.
  • In the main thread wait for worker thread to stop by subscribing to exit event.
  • When worker thread stops, exit from the main thread.
Vikash Kesarwani
Vikash Kesarwani
October 20, 2019 05:24 AM

Related Questions


Updated March 03, 2018 16:26 PM

Updated December 10, 2017 22:26 PM

Updated March 07, 2017 13:26 PM

Updated May 07, 2017 03:26 AM

Updated April 21, 2015 20:11 PM