Really nice explanation of the behavior of the node single threaded event-loop. Much more elaborate and comprehensive than the typical 'Hello world' explanation. Wonder if it could be included in a Node.js wiki page.
On Thu, Mar 15, 2012 at 9:04 PM, C. Mundi <[email protected]> wrote: > This is helpful, and broadens my perspective. Thanks for cleaning up my > nomenclature! > On Mar 15, 2012 3:29 AM, "Jorge" <[email protected]> wrote: > >> On Mar 15, 2012, at 6:53 AM, C. Mundi wrote: >> >> > I know *what* the following code does. I want to understand *why*. >> > >> > Consider the following client/server pair: >> > >> > client.js >> > var net = require('net'); >> > var conn = net.createConnection(8000, function() { // 'connect' >> listener >> > console.error('connected to server'); >> > conn.on('data', function(data) { >> > var msg = data.toString(); >> > console.error('Got data: ' + msg); >> > conn.write('Back at ya!'); >> > conn.end(); // Pay close attention! >> > }); >> > }); >> > >> > server.js >> > var net = require('net'); >> > var server = net.createServer(function(client) { >> > console.error('Accepted connection'); >> > client.on('end', function() { >> > console.error('Client has closed connection.'); >> > }); >> > client.on('data', function(data) { >> > var msg = data.toString(); >> > console.error('Got data: ' + msg); >> > }); >> > client.write('Welcome'); >> > }); >> > >> > server.listen(8000, function() { >> > console.error('Listening on port 8000'); >> > }); >> > >> > So we start the server ('node server.js') and then we run the client >> ('node client.js') and see (as expected) that the server accepts the >> connection from the client, they exchange a pair of messages and the client >> exits. Now let's comment out the 'conn.end()' from the client. Now the >> client hangs around until we kill it. What I want to understand is this: >> how does the V8 thread know that it should or should not hang around? The >> conn.end() is in the 'connect' event listener, which gets registered only >> after the connection is established. (And it is important to notice that >> if the connection had been refused, then the client would have exited with >> an error.) My mental model goes like this, and I would like some feedback: >> > >> > During the execution of each event loop, node memoizes every async call >> long enough to see if the callback could be called. As long as there is at >> least one pending callback (and no error or explicit exit() call) the event >> loop keeps running. Ok. Now let's suppose the server accepts the >> connection. The 'connect' event is caught by the listener callback in the >> client. And after this 'connect' callback executes... node hangs around, >> because the 'connect' callback registered a callback for the 'data' event. >> And event handlers are persistent, so execution keeps looping if the >> conn.end() is not present. Now, somehow, conn.end() breaks us out of the >> loop, at which point there is nothing left to do *and* nothing left to wait >> for, so client.js exits. My guess is that the conn.end() call unregisters >> all the event handlers associated with the connection object conn, at which >> point node has nothing left to do. >> > >> > Am I even close to the right way of thinking about this? >> > >> > Thanks! >> >> The server (server.js): .createServer() creates a socket and then >> .listen() puts it into listen for and accept connections mode, node notices >> that the app is listening for connections so it must flag the event loop >> not to quit (it's really .listen() who flags it, see below). Remove the >> server.listen() or add a server.close() and node will remove the flag and >> then it will quit. >> >> WRT the client (client.js): createConnection() creates a socket and tries >> to connect to a host,port. Node flags the event loop not to quit until that >> connection attempt either fails or succeeds. If the connection succeeds, >> node will remove the flag only after the connection ends/is closed. >> >> For example, in the case of ev_async events, the ones that threads_a_gogo >> (which is an über awesome module btw, check it out! :-) uses, to flag the >> event loop not to quit yet there's an ev_ref() call: >> >> >> https://github.com/xk/node-threads-a-gogo/blob/master/src/threads_a_gogo.cc#L691 >> >> and it's thread.create() who calls it, so that node won't quit as long as >> there's a thread alive. >> >> to remove the flag then I do an ev_unref() call: >> >> >> https://github.com/xk/node-threads-a-gogo/blob/master/src/threads_a_gogo.cc#L358 >> >> and I do that in thread.destroy(), for obvious reasons. >> >> All these ev_ref()s add up, e.g. if I .create() 3 threads and then >> .destroy() 2 of them, there will still be one thread ev_ref()d, so the >> event loop/node won't quit yet. >> >> This is how node 'learns' whether to quit or not. >> >> Hope it helps. Cheers, >> -- >> Jorge. >> >> -- >> Job Board: http://jobs.nodejs.org/ >> Posting guidelines: >> https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines >> You received this message because you are subscribed to the Google >> Groups "nodejs" group. >> To post to this group, send email to [email protected] >> To unsubscribe from this group, send email to >> [email protected] >> For more options, visit this group at >> http://groups.google.com/group/nodejs?hl=en?hl=en >> > -- > Job Board: http://jobs.nodejs.org/ > Posting guidelines: > https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines > You received this message because you are subscribed to the Google > Groups "nodejs" group. > To post to this group, send email to [email protected] > To unsubscribe from this group, send email to > [email protected] > For more options, visit this group at > http://groups.google.com/group/nodejs?hl=en?hl=en > -- Job Board: http://jobs.nodejs.org/ Posting guidelines: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines You received this message because you are subscribed to the Google Groups "nodejs" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/nodejs?hl=en?hl=en
