BTHREADS_BACKEND=child_process SIGINT handling
See original GitHub issueFor my specific use case in a node app, I’d like jobs created as processes (lots of IO and long running). Experimenting with the examples, I’ve come up with the parent / child code as per below. The problem is I cannot get the exception handling to work properly without a “sleep” after it calls bree.stop(). With it, it works as expected. My naive understanding is that signal handlers should not be async in nature. Is there a better way? BTW, same problem exists if I use Graceful.
Main "dispatch" app
const path = require('path');
// optional
const ms = require('ms');
const dayjs = require('dayjs');
const Graceful = require('@ladjs/graceful');
const Cabin = require('cabin');
const later = require('@breejs/later');
// required
const Bree = require('bree');
const sleep = require('util').promisify(setTimeout);
process.on('SIGINT', () => {
myExit('SIGINT');
});
process.on('SIGQUIT', () => {
myExit('SIGQUIT');
});
process.on('SIGTERM', () => {
myExit('SIGTERM');
});
async function myExit(name) {
console.log(`\mBREE Parent Ending ${name}`);
bree.stop();
//removing sleep here now does not allow child to close properly (at least no logging is seen but process is closed)
await sleep(500);
process.exit(0);
}
console.log(`BREE starting with PID:${process.pid}`);
//
// NOTE: see the "Instance Options" section below in this README
// for the complete list of options and their defaults
//
const bree = new Bree({
//
// NOTE: by default the `logger` is set to `console`
// however we recommend you to use CabinJS as it
// will automatically add application and worker metadata
// to your log output, and also masks sensitive data for you
// <https://cabinjs.com>
//
// logger: new Cabin(),
//
// NOTE: instead of passing this Array as an option
// you can create a `./jobs/index.js` file, exporting
// this exact same array as `module.exports = [ ... ]`
// doing so will allow you to keep your job configuration and the jobs
// themselves all in the same folder and very organized
//
// See the "Job Options" section below in this README
// for the complete list of job options and configurations
//
jobs: [
// runs `./jobs/foo.js` on start
// 'job-async',
// 'job-async',
//'job-compute'
// runs `./jobs/worker-5.js` on after 10 minutes have elapsed
{
name: 'job-async-copy',
interval: 5000,//later.parse.text('every 5 seconds'),
worker: {
workerData: { name: 'joe' }
}
},
]
});
// handle graceful reloads, pm2 support, and events like SIGHUP, SIGINT, etc.
// const graceful = new Graceful({ brees: [bree] });
// graceful.listen();
// start all jobs (this is the equivalent of reloading a crontab):
bree.start();
//bree.stop('job-async');
/*
// start only a specific job:
bree.start('foo');
// stop all jobs
bree.stop();
// stop only a specific job:
bree.stop('beep');
// run all jobs (this does not abide by timeout/interval/cron and spawns workers immediately)
bree.run();
// run a specific job (...)
bree.run('beep');
// add a job array after initialization:
bree.add(['boop']);
// this must then be started using one of the above methods
// add a job after initialization:
bree.add('boop');
// this must then be started using one of the above methods
// remove a job after initialization:
bree.remove('boop');
*/
bree.on('worker deleted', (name) => {
console.log('worker deleted', name);
// if (name === 'job-async' && !signal)
// bree.run(name);
});
bree.on('worker created', (name) => {
console.log(`new worker ${name}`);
});
Job
const threads = require('bthreads');
const sleep = require('util').promisify(setTimeout);
let signal = false;
process.on('SIGINT', () => {
myExit('SIGINT');
});
process.on('SIGQUIT', () => {
myExit('SIGQUIT');
});
process.on('SIGTERM', () => {
myExit('SIGTERM');
});
function myExit(name) {
console.log(`ASYNC received ${name}`);
signal = true;
// if (threads.parentPort) {
// threads.parentPort.postMessage('cancel');
// console.log(`Cancel sent`);
// } else
// console.log(`Exiting...`);
}
if (!threads.isMainThread) {
threads.parentPort.on('message', async (message) => {
console.log(`Received message from parent [${message}]`);
// await sleep(300);
if (message === 'cancel') {
signal = true;
}
});
}
if (threads.isMainThread) {
console.log(`ASYNC on main threads`);
} else {
console.log(`ASYNC on worker thread`);
}
// if (threads.parentPort) {
// console.log(`Adding .... event receiver`);
// threads.parentPort.once('message', async (message) => {
// });
// }
let a = 1;
let name = 'll'; //threads.hasOwnProperty('workerData.name') ? "UNKNOWN" : threads.workerData.name
console.log(`async-COPY starting with PID:${process.pid} and name ${name}`);
async function x() {
for (;;) {
a++;
await sleep(300);
console.log(`COPY loop ${a}`);
// if (a==5)
// threads.parentPort.postMessage('error');
if (a>10 || signal) {
// if (threads.parentPort) {
// threads.parentPort.postMessage('COPY exit');
// }
if (signal) {
console.log(`COPY Exiting due to signal...`);
if (!threads.isMainThread) {
console.log(`Sending to Parent...`);
threads.parentPort.postMessage('cancelled');
}
}
process.exit(0);
}
}
}
x();
Issue Analytics
- State:
- Created 3 years ago
- Reactions:1
- Comments:8 (7 by maintainers)
Top Results From Across the Web
Proper handling of SIGINT/SIGQUIT
On first sight, all three solutions (IUE, WUE and WCE) all seem to do what we want: If C-c is hit while the...
Read more >Signal Handler for SIGINT
If I try to send the SIGINT using kill -INT *process pid* it just terminates the program, no msg printed. Any idea why?...
Read more >The Basics of Signal Handling
Signals are one of the most basic ways programs can receive messages from the outside world. I've found limited tutorial-type documentation ...
Read more >Signal Handling
Process can install a signal handler by calling sigaction(2) with the name of ... 2 SIGINT. Interactive attention signal (usually ˆC). Abnormal termination....
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
v3.4.0 released to npm, thank you @naz for the fix and quick PR, truly appreciate your contribution, means a lot.
https://github.com/breejs/bree/releases/tag/v3.4.0
I don’t have time to look at this yet, perhaps @shadowgate15 can