diff --git a/src/node.js b/src/node.js index 115441eb6a..7f762cd413 100644 --- a/src/node.js +++ b/src/node.js @@ -280,8 +280,18 @@ } } - process._tickCallback = function(fromSpinner) { + function maxTickWarn() { + // XXX Remove all this maxTickDepth stuff in 0.11 + var msg = '(node) warning: Recursive process.nextTick detected. ' + + 'This will break in the next version of node. ' + + 'Please use setImmediate for recursive deferral.'; + if (process.traceDeprecation) + console.trace(msg); + else + console.error(msg); + } + process._tickCallback = function(fromSpinner) { // if you add a nextTick in a domain's error handler, then // it's possible to cycle indefinitely. Normally, the tickDone // in the finally{} block below will prevent this, however if @@ -348,6 +358,9 @@ // it won't get fired anyway. if (process._exiting) return; + if (tickDepth >= process.maxTickDepth) + maxTickWarn(); + var tock = { callback: callback }; if (process.domain) tock.domain = process.domain; nextTickQueue.push(tock); diff --git a/test/message/max_tick_depth.js b/test/message/max_tick_depth.js new file mode 100644 index 0000000000..9e10b901f0 --- /dev/null +++ b/test/message/max_tick_depth.js @@ -0,0 +1,30 @@ +// 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'); + +process.maxTickDepth = 10; +var i = 20; +process.nextTick(function f() { + console.error('tick %d', i); + if (i-- > 0) + process.nextTick(f); +}); diff --git a/test/message/max_tick_depth.out b/test/message/max_tick_depth.out new file mode 100644 index 0000000000..aa9876b2be --- /dev/null +++ b/test/message/max_tick_depth.out @@ -0,0 +1,23 @@ +tick 20 +tick 19 +tick 18 +tick 17 +tick 16 +tick 15 +tick 14 +tick 13 +tick 12 +(node) warning: Recursive process.nextTick detected. This will break in the next version of node. Please use setImmediate for recursive deferral. +tick 11 +tick 10 +tick 9 +tick 8 +tick 7 +tick 6 +tick 5 +tick 4 +tick 3 +tick 2 +(node) warning: Recursive process.nextTick detected. This will break in the next version of node. Please use setImmediate for recursive deferral. +tick 1 +tick 0 diff --git a/test/message/max_tick_depth_trace.js b/test/message/max_tick_depth_trace.js new file mode 100644 index 0000000000..e58d04b41c --- /dev/null +++ b/test/message/max_tick_depth_trace.js @@ -0,0 +1,31 @@ +// 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'); + +process.maxTickDepth = 10; +process.traceDeprecation = true; +var i = 20; +process.nextTick(function f() { + console.error('tick %d', i); + if (i-- > 0) + process.nextTick(f); +}); diff --git a/test/message/max_tick_depth_trace.out b/test/message/max_tick_depth_trace.out new file mode 100644 index 0000000000..17cb7a7296 --- /dev/null +++ b/test/message/max_tick_depth_trace.out @@ -0,0 +1,31 @@ +tick 20 +tick 19 +tick 18 +tick 17 +tick 16 +tick 15 +tick 14 +tick 13 +tick 12 +Trace: (node) warning: Recursive process.nextTick detected. This will break in the next version of node. Please use setImmediate for recursive deferral. + at maxTickWarn (node.js:289:17) + at process.nextTick (node.js:362:9) + at f (*test*message*max_tick_depth_trace.js:30:13) + at process._tickCallback (node.js:335:13) +tick 11 +tick 10 +tick 9 +tick 8 +tick 7 +tick 6 +tick 5 +tick 4 +tick 3 +tick 2 +Trace: (node) warning: Recursive process.nextTick detected. This will break in the next version of node. Please use setImmediate for recursive deferral. + at maxTickWarn (node.js:289:17) + at process.nextTick (node.js:362:9) + at f (*test*message*max_tick_depth_trace.js:30:13) + at process._tickCallback (node.js:335:13) +tick 1 +tick 0