3

I have a main process which spawn one new thread using worker_threads. Main process in some particular cases have to close this thread without mattering if it has finished its task or not, so MainThread makes use of terminate() to stop the thread. However, this thread spawn different dependencies that need to be closed before exiting. These dependencies have to be closed from the thread, so I cannot use worker.on('exit') since it is run on main process.

Is there some way of listening the terminate from the worker itself?

Some minimal example of what I would like to achieve.

const {Worker, isMainThread} = require('worker_threads');

if (isMainThread) {
  const worker = new Worker(__filename);
  worker.on('message', console.log);
  worker.on('error', console.log);
  worker.on('exit', console.log);

  setTimeout(() => {
    console.log('Worker is gonna be terminated');
    worker.terminate();
  }, 5000);
} else {
  (async () => {
    console.log('I am the worker');
    // This thread will spawn its own dependencies, so I want to listen here the terminate signal from 
    // mainThread to close the dependencies of this worker
    // Sth like the following will be awesome
    // thread.on('exit', () => { /* close dependencies */ })

    // Simulate a task which takes a larger time than MainThread wants to wait
    await new Promise(resolve => {
      setTimeout(resolve, 10000);
    });
  })();
}
ie8888
  • 171
  • 1
  • 10
  • Terminate execute the function worker.emit('exit'). Then, you can listen it on worker.on('exit', console.log); – Amn Nov 24 '20 at 16:29
  • @Amn yep, but I need to listen from the worker itself. `worker.on('exit', console.log)` is only available at parent process. – ie8888 Dec 01 '20 at 08:20

1 Answers1

2

You can signal exit to the worker thread via worker.postMessage(value) / parentPort.on("message", (value) => {...}), and then use process.exit() in the worker thread. Of course do the clean up first.

I would recommend to use an object as value, that way you will be able to pass multiple commands or date from main thread to worker thread.

const { Worker, isMainThread, parentPort } = require("worker_threads");

if (isMainThread) {
  const worker = new Worker(__filename);
  worker.on("message", console.log);
  worker.on("error", console.log);
  worker.on("exit", console.log);

  setTimeout(() => {
    console.log("Worker is gonna be terminated");
    // replace worker.terminate(); with something like
    worker.postMessage({ exit: true });
    // maybe add another setTimeout with worker.terminate() just in case?
  }, 5000);
} else {
  (async () => {
    // listen for message and do things according to passed value
    parentPort.on("message", (value) => {
      // worker threads do not have multiple listeners available for passing different event,
      // therefore add one onMessage listener, and pass an object with commands/data from main thread
      if (value.exit) {
        // clean up
        console.log("doing cleanup");
        process.exit(0);
      }
    });
    // add other logic for receiving messages from main thread

    console.log("I am the worker");
    // This thread will spawn its own dependencies, so I want to listen here the terminate signal from
    // mainThread to close the dependencies of this worker
    // Sth like the following will be awesome
    // thread.on('exit', () => { /* close dependencies */ })

    // Simulate a task which takes a larger time than MainThread wants to wait
    await new Promise((resolve) => {
      setTimeout(resolve, 10000);
    });
  })();
}
Dharman
  • 30,962
  • 25
  • 85
  • 135
PeterDanis
  • 8,210
  • 2
  • 13
  • 23