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