Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does Node keep a server process alive?

When Node's event loop is fully drained, the process exists. However this doesn't happen on an HTTP server for example, because of server.listen(). But what does that function do exactly?

Looking at the code and an old incomplete answer, it eventually calls self._listen2() which emits a "listening" event on process.nextTick, and gets an async hook ID fromDefaultTriggerAsyncId().

However, I still don't get it. What am I missing here? How does only this code cause the event loop to keep 'idling'? How is the function wrapped on the C side? Where's the line of code that actually does that?

Thanks!

like image 200
Alex D Avatar asked Jan 28 '23 18:01

Alex D


1 Answers

The real answer finally came from Bert Belder, who worked on libuv.

Every time Node queues an action that will resolve at some point in the future, think async functions or timers, it has a ref – a mark to remind itself it’s waiting on some future work. The event loop checks if there are any refs. If the ref counter is 0 , Node exits the process. If there are refs, the event loop goes back to the start and does its thing. You can think of it as a super simple while(refCounter) loop.

So, what happens with a server? This exact process, except the listen function doesn’t decrement the ref counter. The event loop sees there’s always at least one ref left, so it never ends the process instead goes back to the start and loops until something new happens.

You can see this by using server.unref() on the server object with the net or http modules. The unref method, available on other objects as well, tells Node to ignore the ref for that specific function when counting at the end of the event loop. If you run the code below you’ll see Node closes the process, even though it starts listening to the port.

const http = require("http");

    http
      .createServer((req, res) => {
        res.writeHead(200);
        res.end("Bye bye");
      })
      .listen(3333)
      .unref();
like image 124
Alex D Avatar answered Jan 30 '23 07:01

Alex D