Can't kill a specific worker in Node.js cluster using Koa framework
We are using a c++ dll from Node.js server using FFI node module. The C++ dll exposes many functions, that the Node.js server is using.

The C++ dll has a characteristic of getting stuck, in some special scenario. And as yet, we do not have a mechanism to heal this up from within the C++ dll. Due to this, the forthcoming requests go un-addressed, because the dll is single-threaded and can take only one request at a time.

The reason we had to use the cluster-worker topology because, we wanted to control the dll from outside.

We have created a fixed number of forks/workers and they are in a pool. For every incoming request, we are assigning the request to a new worker and using the worker with the dll. Whenever the worker is seen taking more than a "healthy" amount of time, we wish to kill it.

We are facing a specific problem, where we are unable to kill a worker, in case the worker is stuck with the c++ dll not responding. This is needed, because of un-handled cases in the c++ dll.

We referred the code for cluster module of Node.js -https://nodejs.org/api/cluster.html#cluster_worker_process

Here are our code snippets -

server_fork.js

var chalk = require( "chalk" );
var cluster = require( "cluster" );
var os = require( "os" );

if ( cluster.isMaster ) {
    console.log( chalk.red( "[Cluster]" ), "Master process is now running.", process.pid );

    for ( var i = 0, coreCount = 2; i < coreCount ; i++ ) {
        var worker = cluster.fork();
    }

    function messageHandler(msg) {
        console.log('messageHandler')
        if (msg.cmd && msg.cmd === 'notifyRequest') {
          numReqs += 1;
        }
      }


    cluster.on(
        "exit",
        function handleExit( worker, code, signal ) {

            console.log( chalk.yellow( "[Cluster]" ), "Worker has died.", worker.process.pid );
            console.log( chalk.yellow( "[Cluster]" ), "Death was suicide:", worker.exitedAfterDisconnect );

                var worker = cluster.fork();
                console.log('new thread');
        }
    );

    cluster.on(
        "message",
        function handleExit( worker, code, signal ) {
            let timeout
            if (code.cmd == 'started'){
                worker.toBeKilled = true
                timeout = setTimeout(() => {
                    if(worker.toBeKilled){
                        try{
                        console.log('inside worker to be killed')
                        // worker.disconnect()
                        worker.kill()
                        //process.exit(0)
                        // process.exit()
                        }catch(err){
                            console.log('err',err)
                        }

                    }
                  }, 2000);
            } else {
                worker.toBeKilled = false
            }


        }
    );
    function messageHandler(msg) {
        if (msg.cmd && msg.cmd === 'notifyRequest') {
            console.log('notifyRequest');
        }
      }

} else {

    require( "./server" );
    console.log( chalk.red( "[Worker]" ), "Worker has started.", process.pid );
}
server.js

const Koa = require('koa');
var mount = require('koa-mount');
var serve = require('koa-static');
var bodyParser = require('koa-bodyparser');
var koaBody = require('koa-body');
var api = require('./../src/modules/bvp/router.js');
var jwt = require('koa-jwt');

const app = new Koa();
var hbs = require('koa-hbs');
const convert = require('koa-convert');
const co = require('co');

app.use(convert(hbs.middleware({
  viewPath: __dirname + '/../src/views',
})));

app.use(async (ctx, next) => {
  const render = ctx.render;
  ctx.render = async function _convertedRender () {
    return co.call(ctx, render.apply(ctx, arguments));
  }
  await next();
});

if (!process.env.NODE_ENV || process.env.NODE_ENV === 'devlopment') {
  app.use(mount('/swagger', serve(`${process.cwd()}/../swagger`)))
}

app.use(koaBody());
app.use(bodyParser());
app.use(api.routes());

app.listen(3000, function() {
console.log('server started on port 3000');
});


module.exports = app;
controller.js

var som_lib = require('som_lib.js');
const Promise = require('promise');
async function simulate(ctx) {
    var arr = [];
    process.send({ cmd: 'started' });
    var output = som_lib.playLeague();
    process.send({ cmd: 'end' });
    ctx.body = output;
}
module.exports = {
    simulate: simulate
}
In the case of a timeout, when we are trying to kill that particular worker, we are getting the following error -

err { Error: kill ESRCH
at exports._errnoException (util.js:1050:11)
at process.kill (internal/process.js:188:13)
at Timeout.setTimeout [as _onTimeout] (C:\Data\projects\BVP_backend - Copy\bin\server_fork.js:65:33)
at ontimeout (timers.js:386:14)
at tryOnTimeout (timers.js:250:5)
at Timer.listOnTimeout (timers.js:214:5) code: 'ESRCH', errno: 'ESRCH', syscall: 'kill' }
We have already referred a similar problem in Express framework - link https://stackoverflow.com/questions/42106004/cant-kill-a-specific-worker-in-node-js-cluster