Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 829
Patrick Hund Avatar asked Oct 13 '19 16:10

Patrick Hund


2 Answers

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);
  }
});
like image 170
EddieDean Avatar answered Sep 30 '22 14:09

EddieDean


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.
like image 27
Vikash Kesarwani Avatar answered Sep 30 '22 14:09

Vikash Kesarwani