Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

How to end cluster's worker process gracefully? #2088

Closed
avz opened this issue Nov 13, 2011 · 6 comments
Closed

How to end cluster's worker process gracefully? #2088

avz opened this issue Nov 13, 2011 · 6 comments
Labels

Comments

@avz
Copy link

avz commented Nov 13, 2011

How i can cause exit of worker process (end worker's event loop) without calling process.exit()?

var cluster = require('cluster');

if(cluster.isMaster) {
    process.stdout.write('Starting worker ... ')

    cluster.fork();

    cluster.on('death', function(worker) {
        console.log('worker ' + worker.pid + ' died');
    });
} else {
    process.stdout.write('done\n')
    process.stdout.write('Now worker must gracefully die\n')
}

Result

arepo@home [/tmp]# node a.js
Starting worker ... done
Now worker must gracefully die
<...nothing happens...>
^Czsh: exit 1     node a.js

Expected result:

arepo@home [/tmp]# node a.js
Starting worker ... done
Now worker must gracefully die
worker 9992 died
arepo@home [/tmp]#
@bnoordhuis
Copy link
Member

Call process.exit() in the worker. The worker has an open communication channel with the master that's keeping the event loop alive.

@avz
Copy link
Author

avz commented Nov 14, 2011

Well, but we need to syncronize end of all async actions in program because process.exit() may break it. We must to use something like semaphore to avoid it

var cluster = require('cluster');
var http = require('http');

if (cluster.isMaster) {
    cluster.fork();

    cluster.on('death', function(worker) {
        console.log('worker ' + worker.pid + ' died');
    });
} else {
    var semaphore = new Semaphore(1)
    semaphore.on('zero', function() {
        process.exit()
    })

    var server = http.Server(function(req, res) {
        /* ... */

        semaphore.inc()
        try {
            smthAsyncAction(function() {
                semaphore.dec()
            })
        } catch(e) {
            semaphore.dec()
            throw e
        }

        /* ... */
    }).listen(8000);

    server.on('end', function() {
        semaphore.dec()
    })
}

but our code would be much easier if there was a method like cluster.ipc.close():

var cluster = require('cluster');
var http = require('http');

if (cluster.isMaster) {
    cluster.fork();

    cluster.on('death', function(worker) {
        console.log('worker ' + worker.pid + ' died');
    });
} else {
    var server = http.Server(function(req, res) {
        /* ... */

        smthAsyncAction(function() {
            /* ... */
        })

        /* ... */
    }).listen(8000);

    server.on('end', function() {
        cluster.ipc.close()
    })
}

@bnoordhuis
Copy link
Member

@ry I suppose @avz has a point. Maybe add something like a cluster.destroySoon() that unrefs the worker's IPC channel?

@AndreasMadsen
Copy link
Member

I'm working on this in #2038 but I don't know how to close the IPC between master and worker. Can someone give me a hint?

@AndreasMadsen
Copy link
Member

It just got an inspiration worker.process._channel.close(), but I'm not sure it works since there are no IPC when running the .disconnect() method.

@ry
Copy link

ry commented Nov 15, 2011

We can't take API changes in v0.6, sorry. worker.process._channel.close() is the work around for now, yes.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

4 participants