Wrap FD in closure before emitting from Stream.
authorPeter Griess <pg@std.in>
Tue, 15 Jun 2010 20:33:44 +0000 (15:33 -0500)
committerRyan Dahl <ry@tinyclouds.org>
Tue, 15 Jun 2010 22:10:30 +0000 (15:10 -0700)
- Without this, recvMsg can be invoked before the event emitter gets a
  chance to run. In this case, recvMsg.fd will be overwritten and the
  original caller can end up emitting null.

lib/net.js

index 24e1f7aaa3edfe4ed4eba85bbbfe3c1bc2f76fb4..ac5f56825c35db9ed650cfc0945dddbbdaa473e1 100644 (file)
@@ -294,13 +294,21 @@ function setImplmentationMethods (self) {
     self._readImpl = function(buf, off, len, calledByIOWatcher) {
       var bytesRead = recvMsg(self.fd, buf, off, len);
 
-      // Do not emit this in the same stack, otherwise we risk corrupting
-      // our buffer pool which is full of read data, but has not had
-      // had its pointers updated just yet.
+      // Do not emit this in the same stack, otherwise we risk corrupting our
+      // buffer pool which is full of read data, but has not had had its
+      // pointers updated just yet.
+      //
+      // Save off recvMsg.fd in a closure so that, when we emit it later, we're
+      // emitting the same value that we see now. Otherwise, we can end up
+      // calling emit() after recvMsg() has been called again and end up
+      // emitting null (or another FD).
       if (recvMsg.fd !== null) {
-        process.nextTick(function() {
-          self.emit('fd', recvMsg.fd);
-        });
+        (function () {
+          var fd = recvMsg.fd;
+          process.nextTick(function() {
+            self.emit('fd', fd);
+          });
+        })();
       }
 
       return bytesRead;