Как предотвратить немедленное завершение рабочего потока Node.js 12? - PullRequest
4 голосов
/ 13 октября 2019

У меня есть приложение Node.js, работающее на сервере Express, и рабочий поток , который делает что-то через равные промежутки времени.

Когда сервер остановлен, мне нужно очистить соединениево внешнюю систему, которая открывается рабочим потоком при запуске.

Я попытался добавить обработчик для процесса для сигналов SIGTERM и SIGINT, но это не работает, функция обработчика в рабочем потокене вызывается, он сразу завершается с кодом выхода 1, когда родительский процесс получает SIGINT или SIGTERM, хотя у родительского процесса также есть обработчик для них, который действительно вызывается.

Вотпростой пример кода для воспроизведения проблемы:

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);
}

Когда я запускаю soWorker.js , я получаю этот вывод на консоли при прерывании процесса с помощью сочетания клавиш CTRL + C:

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

То, что я ожидаю , произойдетэто:

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

Я ожидаюВызвать функцию stop в рабочем потоке, чтобы я мог использовать ее для закрытия соединения с внешней системой, а затем корректно завершить процесс рабочего потока с кодом возврата 0.

Вместо этого рабочий потокзавершает работу с кодом 1, , который используется по умолчанию, когда рабочий поток останавливается .

Мой вопрос:

Как выполнить код очистки вмой рабочий поток, когда основной процесс завершен?

Я на правильном пути с подходом, описанным выше?

Ответы [ 2 ]

5 голосов
/ 18 октября 2019

Я в основном сплюболлюсь здесь, но я думаю, что это поставит вас на правильный путь:

добавьте в 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);
  }
});
2 голосов
/ 20 октября 2019

Следующее решение должно работать -

  • Подписаться на основной поток message событие в рабочем потоке
  • Подписаться на SIGTERM (или что-то еще) в основном потоке
  • Когда вы перехватываете сигнал в главном потоке, отправляете сообщение в рабочий поток, прося его очистить и выйти. ** Пока не выходите из основного потока **.
  • В основном потоке дождитесь остановки рабочего потока, подписавшись на событие exit.
  • Когда рабочий поток остановится, выйдите изосновная нить.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...