nodejs/node

net: Don't unlink unix socket on server.close()

Open

#19,729 opened on Apr 1, 2018

View on GitHub
 (7 comments) (0 reactions) (0 assignees)JavaScript (117,218 stars) (35,535 forks)batch import
help wantednet

Description

  • Platform: Linux

Right now before an unix socket is closed its file is also unlinked by libuv. This behavior seems to go against the current docs, which explicitly mention that the socket would persist until unlinked (seems to imply this doesn't happen automatically).

This behavior has already been discussed multiple times in past, and every time the result of the conversation appears to have been that it is a bad idea.

Some problems this behavior causes:

  • It makes restarts with little downtime very hard to implement, since normally you would unlink the old socket in your new process immediately before listening to your new one. However, if your old process calls server.close() afterwards, it will unlink your new socket. Bummer.
  • A simple workaround would be not calling server.close(), however now you lose the ability to wait for old connection to die before exiting, and also the ability to not accept new connections before you exit.

The best way to work around this problem I've found so far appears to be this safeListen:

// Edit: Replaced old workaround with a better one. Now we
// just rename the socket after creating it, so libuv can't know
// about the new path and thus can't unlink it.
const fs = require('fs');

function safeListen(httpServer, path, callback) {
    callback = callback || function(error) {
        if (error) {
            httpServer.emit('error', error);
        }
    };

    const tmpPath = path + '.' + process.pid + '.tmp';

    httpServer.listen(tmpPath, (error) => {
        if (error) {
            return callback(error);
        }
    
        fs.rename(tmpPath, path, (error) => {
            if (error) {
                httpServer.close(() => {});
                return callback(error);
            }

            callback(null, httpServer);
        });
    });
};

Contributor guide