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
  • Community
  • @@ -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
  • Community
  • 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
  • Community
  • @@ -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
  • Community
  • @@ -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
    • Community
    • @@ -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
    • Community
    • @@ -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(); + } + }); +}