diff --git a/doc/api/process.markdown b/doc/api/process.markdown index e59baa82e84..eac1d4e1e4f 100644 --- a/doc/api/process.markdown +++ b/doc/api/process.markdown @@ -226,7 +226,7 @@ Example of opening standard input and listening for both events: process.stdin.setEncoding('utf8'); - process.stdin.on('readable', function(chunk) { + process.stdin.on('readable', function() { var chunk = process.stdin.read(); if (chunk !== null) { process.stdout.write('data: ' + chunk); diff --git a/lib/child_process.js b/lib/child_process.js index f6062248565..c8e9e37605a 100644 --- a/lib/child_process.js +++ b/lib/child_process.js @@ -114,6 +114,9 @@ var handleConversion = { 'net.Socket': { send: function(message, socket) { + if (!socket._handle) + return; + // if the socket was created by net.Server if (socket.server) { // the slave should keep track of the socket @@ -142,7 +145,8 @@ var handleConversion = { postSend: function(handle) { // Close the Socket handle after sending it - handle.close(); + if (handle) + handle.close(); }, got: function(message, handle, emit) { @@ -452,6 +456,11 @@ function setupChannel(target, channel) { // convert TCP object to native handle object handle = handleConversion[message.type].send.apply(target, arguments); + // If handle was sent twice, or it is impossible to get native handle + // out of it - just send a text without the handle. + if (!handle) + message = message.msg; + // Update simultaneous accepts on Windows if (obj.simultaneousAccepts) { net._setSimultaneousAccepts(handle); diff --git a/lib/crypto.js b/lib/crypto.js index 2f8e2fa6ab0..464d5be57fe 100644 --- a/lib/crypto.js +++ b/lib/crypto.js @@ -701,8 +701,13 @@ function filterDuplicates(names) { // for example, 'sha1' instead of 'SHA1'. var ctx = {}; names.forEach(function(name) { - if (/^[0-9A-Z\-]+$/.test(name)) name = name.toLowerCase(); - ctx[name] = true; + var key = name; + if (/^[0-9A-Z\-]+$/.test(key)) key = key.toLowerCase(); + if (!ctx.hasOwnProperty(key) || ctx[key] < name) + ctx[key] = name; }); - return Object.getOwnPropertyNames(ctx).sort(); + + return Object.getOwnPropertyNames(ctx).map(function(key) { + return ctx[key]; + }).sort(); } diff --git a/lib/timers.js b/lib/timers.js index 644d4c301cc..183044a2a36 100644 --- a/lib/timers.js +++ b/lib/timers.js @@ -138,9 +138,15 @@ function listOnTimeout() { threw = false; } finally { if (threw) { + // We need to continue processing after domain error handling + // is complete, but not by using whatever domain was left over + // when the timeout threw its exception. + var oldDomain = process.domain; + process.domain = null; process.nextTick(function() { list[kOnTimeout](); }); + process.domain = oldDomain; } } } diff --git a/src/node.h b/src/node.h index d1641f751e2..03cf155af1d 100644 --- a/src/node.h +++ b/src/node.h @@ -325,7 +325,7 @@ extern "C" NODE_EXTERN void node_module_register(void* mod); #ifdef _WIN32 # define NODE_MODULE_EXPORT __declspec(dllexport) #else -# define NODE_MODULE_EXPORT /* empty */ +# define NODE_MODULE_EXPORT __attribute__((visibility("default"))) #endif #if defined(_MSC_VER) diff --git a/test/simple/test-cluster-send-handle-twice.js b/test/simple/test-cluster-send-handle-twice.js new file mode 100644 index 00000000000..3215eae79ed --- /dev/null +++ b/test/simple/test-cluster-send-handle-twice.js @@ -0,0 +1,56 @@ +// 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. + +// Testing to send an handle twice to the parent process. + +var common = require('../common'); +var assert = require('assert'); +var cluster = require('cluster'); +var net = require('net'); + +var workers = { + toStart: 1 +}; + +if (cluster.isMaster) { + for (var i = 0; i < workers.toStart; ++i) { + var worker = cluster.fork(); + worker.on('exit', function(code, signal) { + assert.equal(code, 0, 'Worker exited with an error code'); + assert(!signal, 'Worker exited by a signal'); + }); + } +} else { + var server = net.createServer(function(socket) { + process.send('send-handle-1', socket); + process.send('send-handle-2', socket); + }); + + server.listen(common.PORT, function() { + var client = net.connect({ host: 'localhost', port: common.PORT }); + client.on('close', function() { cluster.worker.disconnect(); }); + setTimeout(function() { client.end(); }, 50); + }).on('error', function(e) { + console.error(e); + assert(false, 'server.listen failed'); + cluster.worker.disconnect(); + }); +} diff --git a/test/simple/test-crypto.js b/test/simple/test-crypto.js index 39fc1216aae..e1b26821241 100644 --- a/test/simple/test-crypto.js +++ b/test/simple/test-crypto.js @@ -1008,6 +1008,8 @@ assert.notEqual(-1, crypto.getHashes().indexOf('sha1')); assert.notEqual(-1, crypto.getHashes().indexOf('sha')); assert.equal(-1, crypto.getHashes().indexOf('SHA1')); assert.equal(-1, crypto.getHashes().indexOf('SHA')); +assert.notEqual(-1, crypto.getHashes().indexOf('RSA-SHA1')); +assert.equal(-1, crypto.getHashes().indexOf('rsa-sha1')); assertSorted(crypto.getHashes()); // Base64 padding regression test, see #4837. diff --git a/test/simple/test-domain-exit-dispose-again.js b/test/simple/test-domain-exit-dispose-again.js new file mode 100644 index 00000000000..22928f26045 --- /dev/null +++ b/test/simple/test-domain-exit-dispose-again.js @@ -0,0 +1,76 @@ +// 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.js'); +var assert = require('assert'); +var domain = require('domain'); +var disposalFailed = false; + +// no matter what happens, we should increment a 10 times. +var a = 0; +log(); +function log(){ + console.log(a++, process.domain); + if (a < 10) setTimeout(log, 20); +} + +var secondTimerRan = false; + +// in 50ms we'll throw an error. +setTimeout(err, 50); +setTimeout(secondTimer, 50); +function err(){ + var d = domain.create(); + d.on('error', handle); + d.run(err2); + + function err2() { + // this timeout should never be called, since the domain gets + // disposed when the error happens. + setTimeout(function() { + console.error('This should not happen.'); + disposalFailed = true; + process.exit(1); + }); + + // this function doesn't exist, and throws an error as a result. + err3(); + } + + function handle(e) { + // this should clean up everything properly. + d.dispose(); + console.error(e); + console.error('in handler', process.domain, process.domain === d); + } +} + +function secondTimer() { + console.log('In second timer'); + secondTimerRan = true; +} + +process.on('exit', function() { + assert.equal(a, 10); + assert.equal(disposalFailed, false); + assert(secondTimerRan); + console.log('ok'); +}); diff --git a/test/simple/test-next-tick-domain.js b/test/simple/test-next-tick-domain.js new file mode 100644 index 00000000000..16f77ed94d5 --- /dev/null +++ b/test/simple/test-next-tick-domain.js @@ -0,0 +1,29 @@ +// 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 origNextTick = process.nextTick; + +require('domain'); + +assert.strictEqual(origNextTick, process.nextTick, 'Requiring domain should not change nextTick');