From 1c2b03dea5846916073efeb90f3c56db09e0dec5 Mon Sep 17 00:00:00 2001
From: Kevin Locke
Date: Fri, 26 Apr 2013 17:14:39 -0600
Subject: [PATCH 01/10] doc: update options for exec and execFile
The stdio and customFds options are never used by exec or execFile,
remove them from the documentation for these functions.
---
doc/api/child_process.markdown | 8 --------
1 file changed, 8 deletions(-)
diff --git a/doc/api/child_process.markdown b/doc/api/child_process.markdown
index dade323564..85c9c8b8d4 100644
--- a/doc/api/child_process.markdown
+++ b/doc/api/child_process.markdown
@@ -466,11 +466,6 @@ See also: `child_process.exec()` and `child_process.fork()`
* `command` {String} The command to run, with space-separated arguments
* `options` {Object}
* `cwd` {String} Current working directory of the child process
- * `stdio` {Array|String} Child's stdio configuration. (See above)
- Only stdin is configurable, anything else will lead to unpredictable
- results.
- * `customFds` {Array} **Deprecated** File descriptors for the child to use
- for stdio. (See above)
* `env` {Object} Environment key-value pairs
* `encoding` {String} (Default: 'utf8')
* `timeout` {Number} (Default: 0)
@@ -524,9 +519,6 @@ the child process is killed.
* `args` {Array} List of string arguments
* `options` {Object}
* `cwd` {String} Current working directory of the child process
- * `stdio` {Array|String} Child's stdio configuration. (See above)
- * `customFds` {Array} **Deprecated** File descriptors for the child to use
- for stdio. (See above)
* `env` {Object} Environment key-value pairs
* `encoding` {String} (Default: 'utf8')
* `timeout` {Number} (Default: 0)
From 76cbd039b93905df1144d5ce8625d3c35a5244cc Mon Sep 17 00:00:00 2001
From: Timothy J Fontaine
Date: Thu, 2 May 2013 13:54:37 -0700
Subject: [PATCH 02/10] build: only use DESTDIR instead of PREFIX for pkg
Preserve default install prefix seen in process.config, but use DESTDIR
for installing to deliniate 32/64 versions, avoid conflicts with PREFIX
settings in config.mk
---
Makefile | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/Makefile b/Makefile
index ae05f4dc71..a3532f11ba 100644
--- a/Makefile
+++ b/Makefile
@@ -266,11 +266,11 @@ pkg: $(PKG)
$(PKG): release-only
rm -rf $(PKGDIR)
rm -rf out/deps out/Release
- $(PYTHON) ./configure --prefix=$(PKGDIR)/32/usr/local --without-snapshot --dest-cpu=ia32 --tag=$(TAG)
- $(MAKE) install V=$(V)
+ $(PYTHON) ./configure --without-snapshot --dest-cpu=ia32 --tag=$(TAG)
+ $(MAKE) install V=$(V) DESTDIR=$(PKGDIR)/32
rm -rf out/deps out/Release
- $(PYTHON) ./configure --prefix=$(PKGDIR)/usr/local --without-snapshot --dest-cpu=x64 --tag=$(TAG)
- $(MAKE) install V=$(V)
+ $(PYTHON) ./configure --without-snapshot --dest-cpu=x64 --tag=$(TAG)
+ $(MAKE) install V=$(V) DESTDIR=$(PKGDIR)
SIGN="$(SIGN)" PKGDIR="$(PKGDIR)" bash tools/osx-codesign.sh
lipo $(PKGDIR)/32/usr/local/bin/node \
$(PKGDIR)/usr/local/bin/node \
From 716176fa997c554e424485897894ec2898f8254f Mon Sep 17 00:00:00 2001
From: Timothy J Fontaine
Date: Tue, 7 May 2013 11:59:22 -0700
Subject: [PATCH 03/10] test: report test duration in TAP progress
---
tools/test.py | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/tools/test.py b/tools/test.py
index 90c79bcb35..7d5ddc69da 100755
--- a/tools/test.py
+++ b/tools/test.py
@@ -39,6 +39,7 @@ import subprocess
import sys
import tempfile
import time
+import datetime
import threading
from Queue import Queue, Empty
@@ -115,9 +116,9 @@ class ProgressIndicator(object):
self.AboutToRun(case)
self.lock.release()
try:
- start = time.time()
+ start = datetime.datetime.now()
output = case.Run()
- case.duration = (time.time() - start)
+ case.duration = (datetime.datetime.now() - start)
except IOError, e:
assert self.terminate
return
@@ -242,6 +243,12 @@ class TapProgressIndicator(SimpleProgressIndicator):
else:
print 'ok %i - %s' % (self._done, command)
+ duration = output.test.duration
+
+ print ' ---'
+ print ' duration_ms: %d.%d' % (duration.total_seconds(), duration.microseconds / 1000)
+ print ' ...'
+
def Done(self):
pass
From cf87ee67eed4409bdd14a4d75b5d7053328cce91 Mon Sep 17 00:00:00 2001
From: Timothy J Fontaine
Date: Tue, 7 May 2013 15:17:33 -0700
Subject: [PATCH 04/10] test: don't use total_seconds() because of py2.6
---
tools/test.py | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/tools/test.py b/tools/test.py
index 7d5ddc69da..c922c40f7e 100755
--- a/tools/test.py
+++ b/tools/test.py
@@ -31,7 +31,6 @@
import imp
import optparse
import os
-from os.path import join, dirname, abspath, basename, isdir, exists
import platform
import re
import signal
@@ -39,8 +38,10 @@ import subprocess
import sys
import tempfile
import time
-import datetime
import threading
+
+from os.path import join, dirname, abspath, basename, isdir, exists
+from datetime import datetime
from Queue import Queue, Empty
sys.path.append(dirname(__file__) + "/../deps/v8/tools");
@@ -116,9 +117,9 @@ class ProgressIndicator(object):
self.AboutToRun(case)
self.lock.release()
try:
- start = datetime.datetime.now()
+ start = datetime.now()
output = case.Run()
- case.duration = (datetime.datetime.now() - start)
+ case.duration = (datetime.now() - start)
except IOError, e:
assert self.terminate
return
@@ -245,8 +246,12 @@ class TapProgressIndicator(SimpleProgressIndicator):
duration = output.test.duration
+ # total_seconds() was added in 2.7
+ total_seconds = (duration.microseconds +
+ (duration.seconds + duration.days * 24 * 3600) * 10**6) / 10**6
+
print ' ---'
- print ' duration_ms: %d.%d' % (duration.total_seconds(), duration.microseconds / 1000)
+ print ' duration_ms: %d.%d' % (total_seconds, duration.microseconds / 1000)
print ' ...'
def Done(self):
From 1ad93a65844e6bf5c87fb4c5ca46f9c7fb2ebc9f Mon Sep 17 00:00:00 2001
From: Daniel Moore
Date: Mon, 29 Apr 2013 09:25:08 -0400
Subject: [PATCH 05/10] stream: make Readable.wrap support objectMode
Added a check to see if the stream is in objectMode before deciding
whether to include or exclude data from an old-style wrapped stream.
---
lib/_stream_readable.js | 2 +-
test/simple/test-stream2-readable-wrap.js | 116 ++++++++++++----------
2 files changed, 66 insertions(+), 52 deletions(-)
diff --git a/lib/_stream_readable.js b/lib/_stream_readable.js
index 070628288e..63babe4265 100644
--- a/lib/_stream_readable.js
+++ b/lib/_stream_readable.js
@@ -767,7 +767,7 @@ Readable.prototype.wrap = function(stream) {
stream.on('data', function(chunk) {
if (state.decoder)
chunk = state.decoder.write(chunk);
- if (!chunk || !chunk.length)
+ if (!chunk || !state.objectMode && !chunk.length)
return;
var ret = self.push(chunk);
diff --git a/test/simple/test-stream2-readable-wrap.js b/test/simple/test-stream2-readable-wrap.js
index 5fa5d185b5..6b272be46b 100644
--- a/test/simple/test-stream2-readable-wrap.js
+++ b/test/simple/test-stream2-readable-wrap.js
@@ -26,69 +26,83 @@ var Readable = require('_stream_readable');
var Writable = require('_stream_writable');
var EE = require('events').EventEmitter;
-var old = new EE;
-var r = new Readable({ highWaterMark: 10 });
-assert.equal(r, r.wrap(old));
+var testRuns = 0, completedRuns = 0;
+function runTest(highWaterMark, objectMode, produce) {
+ testRuns++;
-var ended = false;
-r.on('end', function() {
- ended = true;
-});
+ var old = new EE;
+ var r = new Readable({ highWaterMark: highWaterMark, objectMode: objectMode });
+ assert.equal(r, r.wrap(old));
-var pauses = 0;
-var resumes = 0;
+ var ended = false;
+ r.on('end', function() {
+ ended = true;
+ });
-old.pause = function() {
- pauses++;
- old.emit('pause');
- flowing = false;
-};
+ var pauses = 0;
+ var resumes = 0;
-old.resume = function() {
- resumes++;
- old.emit('resume');
- flow();
-};
-
-var flowing;
-var chunks = 10;
-var oldEnded = false;
-function flow() {
- flowing = true;
- while (flowing && chunks-- > 0) {
- old.emit('data', new Buffer('xxxxxxxxxx'));
- }
- if (chunks <= 0) {
- oldEnded = true;
- old.emit('end');
+ old.pause = function() {
+ pauses++;
+ old.emit('pause');
+ flowing = false;
+ };
+
+ old.resume = function() {
+ resumes++;
+ old.emit('resume');
+ flow();
+ };
+
+ var flowing;
+ var chunks = 10;
+ var oldEnded = false;
+ var expected = [];
+ function flow() {
+ flowing = true;
+ while (flowing && chunks-- > 0) {
+ var item = produce();
+ expected.push(item);
+ console.log('emit', chunks);
+ old.emit('data', item);
+ }
+ if (chunks <= 0) {
+ oldEnded = true;
+ console.log('old end', chunks, flowing);
+ old.emit('end');
+ }
}
-}
-var w = new Writable({ highWaterMark: 20 });
-var written = [];
-w._write = function(chunk, encoding, cb) {
- written.push(chunk.toString());
- setTimeout(cb);
-};
+ var w = new Writable({ highWaterMark: highWaterMark * 2, objectMode: objectMode });
+ var written = [];
+ w._write = function(chunk, encoding, cb) {
+ console.log(chunk);
+ written.push(chunk);
+ setTimeout(cb);
+ };
-var finished = false;
-w.on('finish', function() {
- finished = true;
-});
+ w.on('finish', function() {
+ completedRuns++;
+ performAsserts();
+ });
+ r.pipe(w);
-var expect = new Array(11).join('xxxxxxxxxx');
+ flow();
-r.pipe(w);
+ function performAsserts() {
+ assert(ended);
+ assert(oldEnded);
+ assert.deepEqual(written, expected);
+ assert.equal(pauses, 10);
+ assert.equal(resumes, 9);
+ }
+}
-flow();
+runTest(10, false, function(){ return new Buffer('xxxxxxxxxx'); });
+runTest(1, true, function(){ return { foo: 'bar' }; });
process.on('exit', function() {
- assert.equal(pauses, 10);
- assert.equal(resumes, 9);
- assert(ended);
- assert(finished);
- assert(oldEnded);
- assert.equal(written.join(''), expect);
+ assert.equal(testRuns, completedRuns);
console.log('ok');
});
From 3b6fc600e2270b213450517c1406c26f0935e920 Mon Sep 17 00:00:00 2001
From: Daniel Moore
Date: Wed, 1 May 2013 13:46:31 -0400
Subject: [PATCH 06/10] stream: make Readable.wrap support empty streams
This makes Readable.wrap behave properly when the wrapped stream ends
before emitting any data events.
---
lib/_stream_readable.js | 1 -
.../test-stream2-readable-wrap-empty.js | 43 +++++++++++++++++++
2 files changed, 43 insertions(+), 1 deletion(-)
create mode 100644 test/simple/test-stream2-readable-wrap-empty.js
diff --git a/lib/_stream_readable.js b/lib/_stream_readable.js
index 63babe4265..07bd8b046e 100644
--- a/lib/_stream_readable.js
+++ b/lib/_stream_readable.js
@@ -759,7 +759,6 @@ Readable.prototype.wrap = function(stream) {
if (chunk && chunk.length)
self.push(chunk);
}
- state.ended = true;
self.push(null);
});
diff --git a/test/simple/test-stream2-readable-wrap-empty.js b/test/simple/test-stream2-readable-wrap-empty.js
new file mode 100644
index 0000000000..c7042f1b12
--- /dev/null
+++ b/test/simple/test-stream2-readable-wrap-empty.js
@@ -0,0 +1,43 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+var common = require('../common');
+var assert = require('assert');
+
+var Readable = require('_stream_readable');
+var EE = require('events').EventEmitter;
+
+var oldStream = new EE();
+oldStream.pause = function(){};
+oldStream.resume = function(){};
+
+var newStream = new Readable().wrap(oldStream);
+
+var ended = false;
+newStream
+ .on('readable', function(){})
+ .on('end', function(){ ended = true; });
+
+oldStream.emit('end');
+
+process.on('exit', function(){
+ assert.ok(ended);
+});
\ No newline at end of file
From dc92ff85851efdbc5ddb44150a95265982437a59 Mon Sep 17 00:00:00 2001
From: Robert Kowalski
Date: Mon, 6 May 2013 21:53:35 +0200
Subject: [PATCH 07/10] doc: document stream.Writable 'error' event
Fixes #5255.
---
doc/api/stream.markdown | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/doc/api/stream.markdown b/doc/api/stream.markdown
index ce7656b8d7..f71a15693d 100644
--- a/doc/api/stream.markdown
+++ b/doc/api/stream.markdown
@@ -529,6 +529,10 @@ Emitted when the stream's write queue empties and it's safe to write
without buffering again. Listen for it when `stream.write()` returns
`false`.
+### Event: 'error'
+
+Emitted if there was an error receiving data.
+
### Event: 'close'
Emitted when the underlying resource (for example, the backing file
From 72c58158f7a8bd08a0af085f0e2012cfccbf19b5 Mon Sep 17 00:00:00 2001
From: Timothy J Fontaine
Date: Mon, 6 May 2013 16:37:03 -0700
Subject: [PATCH 08/10] test: fix pummel/test-net-many-clients.js
client sockets no longer emit 'connect' event inside the
requestListener, update test-net-many-clients to reflect that
---
test/pummel/test-net-many-clients.js | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/test/pummel/test-net-many-clients.js b/test/pummel/test-net-many-clients.js
index 3f394b8abe..83ff181990 100644
--- a/test/pummel/test-net-many-clients.js
+++ b/test/pummel/test-net-many-clients.js
@@ -37,12 +37,11 @@ for (var i = 0; i < bytes; i++) {
}
var server = net.createServer(function(c) {
- c.on('connect', function() {
- total_connections++;
- common.print('#');
- c.write(body);
- c.end();
- });
+ console.log('connected');
+ total_connections++;
+ common.print('#');
+ c.write(body);
+ c.end();
});
function runClient(callback) {
From 4b69bcfc66c2007a0550e928956bda0006c21aec Mon Sep 17 00:00:00 2001
From: isaacs
Date: Thu, 9 May 2013 15:15:39 -0700
Subject: [PATCH 09/10] doc: s/search.npmjs.org/npmjs.org/
---
README.md | 2 +-
doc/about/index.html | 4 ++--
doc/blog.html | 4 ++--
doc/blog/Uncategorized/version-0-6.md | 17 ++++++++++++++---
doc/changelog-foot.html | 2 +-
doc/changelog-head.html | 2 +-
doc/community/index.html | 6 +++---
doc/download/index.html | 4 ++--
doc/index.html | 4 ++--
doc/logos/index.html | 4 ++--
doc/template.html | 4 ++--
11 files changed, 32 insertions(+), 21 deletions(-)
diff --git a/README.md b/README.md
index d3ffbd0145..aa505e555b 100644
--- a/README.md
+++ b/README.md
@@ -51,7 +51,7 @@ Resources for Newcomers
- [nodejs.org](http://nodejs.org/)
- [how to install node.js and npm (node package manager)](http://joyeur.com/2010/12/10/installing-node-and-npm/)
- [list of modules](https://github.com/joyent/node/wiki/modules)
- - [searching the npm registry](http://search.npmjs.org/)
+ - [searching the npm registry](http://npmjs.org/)
- [list of companies and projects using node](https://github.com/joyent/node/wiki/Projects,-Applications,-and-Companies-Using-Node)
- [node.js mailing list](http://groups.google.com/group/nodejs)
- irc chatroom, [#node.js on freenode.net](http://webchat.freenode.net?channels=node.js&uio=d4)
diff --git a/doc/about/index.html b/doc/about/index.html
index 43422a662d..f1dea6b243 100644
--- a/doc/about/index.html
+++ b/doc/about/index.html
@@ -24,7 +24,7 @@
Home
Download
About
- npm Registry
+ npm Registry
Docs
Blog
@@ -116,7 +116,7 @@ console.log('Server running at http://127.0.0.1:1337/');
Node.js
Download
About
- npm Registry
+ npm Registry
Docs
Blog
Community
diff --git a/doc/blog.html b/doc/blog.html
index 4aa9d8de38..f6d9cf805b 100644
--- a/doc/blog.html
+++ b/doc/blog.html
@@ -86,7 +86,7 @@
About
- npm
+ npm
Registry
Docs
@@ -213,7 +213,7 @@
Node.js
Download
About
- npm Registry
+ npm Registry
Docs
Blog
Community
diff --git a/doc/blog/Uncategorized/version-0-6.md b/doc/blog/Uncategorized/version-0-6.md
index 8dd9719e71..5cde4c61e7 100644
--- a/doc/blog/Uncategorized/version-0-6.md
+++ b/doc/blog/Uncategorized/version-0-6.md
@@ -5,8 +5,19 @@ status: publish
category: Uncategorized
slug: version-0-6
-Version 0.6.0 will be released next week. Please spend some time this week upgrading your code to v0.5.10. Report any API differences at https://github.com/joyent/node/wiki/API-changes-between-v0.4-and-v0.6 or report a bug to us at http://github.com/joyent/node/issues if you hit problems.
+Version 0.6.0 will be released next week. Please spend some time this
+week upgrading your code to v0.5.10. Report any API differences at https://github.com/joyent/node/wiki/API-changes-between-v0.4-and-v0.6
+or report a bug to us at http://github.com/joyent/node/issues
+if you hit problems.
-The API changes between v0.4.12 and v0.5.10 are 99% cosmetic, minor, and easy to fix. Most people are able to migrate their code in 10 minutes. Don't fear.
+The API changes between v0.4.12 and v0.5.10 are 99% cosmetic, minor,
+and easy to fix. Most people are able to migrate their code in 10
+minutes. Don't fear.
-Once you've ported your code to v0.5.10 please help out by testing third party modules. Make bug reports. Encourage authors to publish new versions of their modules. Go through the list of modules at http://search.npmjs.org/ and try out random ones. This is especially encouraged of Windows users!
+Once you've ported your code to v0.5.10 please help out by testing
+third party modules. Make bug reports. Encourage authors to publish
+new versions of their modules. Go through the list of modules at http://npmjs.org/ and try out random
+ones. This is especially encouraged of Windows users!
diff --git a/doc/changelog-foot.html b/doc/changelog-foot.html
index 427359c804..ff760e7c0b 100644
--- a/doc/changelog-foot.html
+++ b/doc/changelog-foot.html
@@ -7,7 +7,7 @@
Node.js
Download
About
- npm Registry
+ npm Registry
Docs
Blog
Community
diff --git a/doc/changelog-head.html b/doc/changelog-head.html
index fdab340267..946904d05d 100644
--- a/doc/changelog-head.html
+++ b/doc/changelog-head.html
@@ -19,7 +19,7 @@
Home
Download
About
- npm Registry
+ npm Registry
Docs
Blog
diff --git a/doc/community/index.html b/doc/community/index.html
index 42a4140706..e47182d59e 100644
--- a/doc/community/index.html
+++ b/doc/community/index.html
@@ -28,7 +28,7 @@
Home
Download
About
- npm Registry
+ npm Registry
Docs
Blog
@@ -93,7 +93,7 @@
Projects, Applications, and Companies Using Node or the
very long
list of Node modules, many of which are published in the
- npm registry.
+ npm registry.
@@ -223,7 +223,7 @@
Node.js
Download
About
- npm Registry
+ npm Registry
Docs
Blog
Community
diff --git a/doc/download/index.html b/doc/download/index.html
index a4559b620b..c17f61bd3e 100644
--- a/doc/download/index.html
+++ b/doc/download/index.html
@@ -24,7 +24,7 @@
Home
Download
About
- npm Registry
+ npm Registry
Docs
Blog
@@ -162,7 +162,7 @@
Node.js
Download
About
- npm Registry
+ npm Registry
Docs
Blog
Community
diff --git a/doc/index.html b/doc/index.html
index 65f200910b..586ada181d 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -118,7 +118,7 @@ server.listen(1337, '127.0.0.1');
Explore Node.js
- About
Technical overview
- - npm Registry
Modules, resources and more
+ - npm Registry
Modules, resources and more
- Documentation
API Specifications
- Node.js Blog
Insight, perspective and events
- Community
Mailing lists, blogs, and more
@@ -134,7 +134,7 @@ server.listen(1337, '127.0.0.1');
- Node.js
- Download
- About
- - npm Registry
+ - npm Registry
- Docs
- Blog
- Community
diff --git a/doc/logos/index.html b/doc/logos/index.html
index c07d4c7dd5..be0559252f 100644
--- a/doc/logos/index.html
+++ b/doc/logos/index.html
@@ -24,7 +24,7 @@
- Home
- Download
- About
- - npm Registry
+ - npm Registry
- Docs
- Blog
@@ -68,7 +68,7 @@
- Node.js
- Download
- About
- - npm Registry
+ - npm Registry
- Docs
- Blog
- Community
diff --git a/doc/template.html b/doc/template.html
index 709c8e8234..7c40bede96 100644
--- a/doc/template.html
+++ b/doc/template.html
@@ -19,7 +19,7 @@
- Home
- Download
- About
- - npm Registry
+ - npm Registry
- Docs
- Blog
@@ -58,7 +58,7 @@
- Node.js
- Download
- About
- - npm Registry
+ - npm Registry
- Docs
- Blog
- Community
From 21bd45676390fd21ffa7c3cca91af4ad37ed3e5c Mon Sep 17 00:00:00 2001
From: Ben Noordhuis
Date: Fri, 10 May 2013 11:19:17 -0700
Subject: [PATCH 10/10] child_process: fix handle delivery
Commit 9352c19 ("child_process: don't emit same handle twice") trades
one bug for another.
Before said commit, a handle was sometimes delivered with messages it
didn't belong to.
The bug fix introduced another bug that needs some explaining. On UNIX
systems, handles are basically file descriptors that are passed around
with the sendmsg() and recvmsg() system calls, using auxiliary data
(SCM_RIGHTS) as the transport.
node.js and libuv depend on the fact that none of the supported systems
ever emit more than one SCM_RIGHTS message from a recvmsg() syscall.
That assumption is something we should probably address someday for the
sake of portability but that's a separate discussion.
So, SCM_RIGHTS messages are never coalesced. SCM_RIGHTS and normal
messages however _are_ coalesced. That is, recvmsg() might return this:
recvmsg(); // { "message-with-fd", "message", "message" }
The operating system implicitly breaks pending messages along
SCM_RIGHTS boundaries. Most Unices break before such messages but Linux
also breaks _after_ them. When the sender looks like this:
sendmsg("message");
sendmsg("message-with-fd");
sendmsg("message");
Then on most Unices the receiver sees messages arriving like this:
recvmsg(); // { "message" }
recvmsg(); // { "message-with-fd", "message" }
The bug fix in commit 9352c19 assumes this behavior. On Linux however,
those messages can also come in like this:
recvmsg(); // { "message", "message-with-fd" }
recvmsg(); // { "message" }
In other words, it's incorrect to assume that the file descriptor is
always attached to the first message. This commit makes node wise up.
Fixes #5330.
---
lib/child_process.js | 9 +-
test/simple/test-child-process-recv-handle.js | 85 +++++++++++++++++++
2 files changed, 92 insertions(+), 2 deletions(-)
create mode 100644 test/simple/test-child-process-recv-handle.js
diff --git a/lib/child_process.js b/lib/child_process.js
index 1b6b8b21d6..f7312215cd 100644
--- a/lib/child_process.js
+++ b/lib/child_process.js
@@ -336,8 +336,13 @@ function setupChannel(target, channel) {
var json = jsonBuffer.slice(start, i);
var message = JSON.parse(json);
- handleMessage(target, message, recvHandle);
- recvHandle = undefined;
+ // There will be at most one NODE_HANDLE message in every chunk we
+ // read because SCM_RIGHTS messages don't get coalesced. Make sure
+ // that we deliver the handle with the right message however.
+ if (message && message.cmd === 'NODE_HANDLE')
+ handleMessage(target, message, recvHandle);
+ else
+ handleMessage(target, message, undefined);
start = i + 1;
}
diff --git a/test/simple/test-child-process-recv-handle.js b/test/simple/test-child-process-recv-handle.js
new file mode 100644
index 0000000000..dce5bdcbaf
--- /dev/null
+++ b/test/simple/test-child-process-recv-handle.js
@@ -0,0 +1,85 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+// Test that a Linux specific quirk in the handle passing protocol is handled
+// correctly. See https://github.com/joyent/node/issues/5330 for details.
+
+var common = require('../common');
+var assert = require('assert');
+var net = require('net');
+var spawn = require('child_process').spawn;
+
+if (process.argv[2] === 'worker')
+ worker();
+else
+ master();
+
+function master() {
+ // spawn() can only create one IPC channel so we use stdin/stdout as an
+ // ad-hoc command channel.
+ var proc = spawn(process.execPath, [__filename, 'worker'], {
+ stdio: ['pipe', 'pipe', 'pipe', 'ipc']
+ });
+ var handle = null;
+ proc.on('exit', function() {
+ handle.close();
+ });
+ proc.stdout.on('data', function(data) {
+ assert.equal(data, 'ok\r\n');
+ net.createServer(assert.fail).listen(common.PORT, function() {
+ handle = this._handle;
+ proc.send('one');
+ proc.send('two', handle);
+ proc.send('three');
+ proc.stdin.write('ok\r\n');
+ });
+ });
+ proc.stderr.pipe(process.stderr);
+}
+
+function worker() {
+ process._channel.readStop(); // Make messages batch up.
+ process.stdout.ref();
+ process.stdout.write('ok\r\n');
+ process.stdin.once('data', function(data) {
+ assert.equal(data, 'ok\r\n');
+ process._channel.readStart();
+ });
+ var n = 0;
+ process.on('message', function(msg, handle) {
+ n += 1;
+ if (n === 1) {
+ assert.equal(msg, 'one');
+ assert.equal(handle, undefined);
+ }
+ else if (n === 2) {
+ assert.equal(msg, 'two');
+ assert.equal(typeof handle, 'object'); // Also matches null, therefore...
+ assert.ok(handle); // also check that it's truthy.
+ handle.close();
+ }
+ else if (n === 3) {
+ assert.equal(msg, 'three');
+ assert.equal(handle, undefined);
+ process.exit();
+ }
+ });
+}