Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

Readable implementation causes stack size to be exceeded #8291

Closed
malern opened this issue Aug 29, 2014 · 1 comment
Closed

Readable implementation causes stack size to be exceeded #8291

malern opened this issue Aug 29, 2014 · 1 comment
Labels

Comments

@malern
Copy link

malern commented Aug 29, 2014

I am attempting to create a stream.Readable subclass by implementing the _read method as described in the docs. But even the very basic implementation shown below causes "recursion detected" warnings followed by eventual stack exhaustion.

var Readable = require('stream').Readable;
var util = require('util');
util.inherits(SimpleRead, Readable);

function SimpleRead(opt) {
    Readable.call(this, opt);
}

SimpleRead.prototype._read = function(size) {
    this.push(new Buffer(size));
};

var s = new SimpleRead();

s.on('readable', function() {
    s.read();
});

The output I get is

(node) warning: Recursive process.nextTick detected. This will break in the next version of node. Please use setImmediate for recursive deferral.
(node) warning: Recursive process.nextTick detected. This will break in the next version of node. Please use setImmediate for recursive deferral.
(node) warning: Recursive process.nextTick detected. This will break in the next version of node. Please use setImmediate for recursive deferral.
(node) warning: Recursive process.nextTick detected. This will break in the next version of node. Please use setImmediate for recursive deferral.
(node) warning: Recursive process.nextTick detected. This will break in the next version of node. Please use setImmediate for recursive deferral.
(node) warning: Recursive process.nextTick detected. This will break in the next version of node. Please use setImmediate for recursive deferral.
(node) warning: Recursive process.nextTick detected. This will break in the next version of node. Please use setImmediate for recursive deferral.
(node) warning: Recursive process.nextTick detected. This will break in the next version of node. Please use setImmediate for recursive deferral.
(node) warning: Recursive process.nextTick detected. This will break in the next version of node. Please use setImmediate for recursive deferral.
(node) warning: Recursive process.nextTick detected. This will break in the next version of node. Please use setImmediate for recursive deferral.
(node) warning: Recursive process.nextTick detected. This will break in the next version of node. Please use setImmediate for recursive deferral.
(node) warning: Recursive process.nextTick detected. This will break in the next version of node. Please use setImmediate for recursive deferral.
(node) warning: Recursive process.nextTick detected. This will break in the next version of node. Please use setImmediate for recursive deferral.
(node) warning: Recursive process.nextTick detected. This will break in the next version of node. Please use setImmediate for recursive deferral.
(node) warning: Recursive process.nextTick detected. This will break in the next version of node. Please use setImmediate for recursive deferral.
(node) warning: Recursive process.nextTick detected. This will break in the next version of node. Please use setImmediate for recursive deferral.

RangeError: Maximum call stack size exceeded

I am using node-v0.10.31-linux-x64

@vkurchatkin
Copy link

@malern basically a duplicate of #7401, also not a bug (in my opinion)

neither event emitters nor streams are asynchronous themselves, so they can cause stack overflow in case of recursion. Simple example:

var EventEmitter = require('events').EventEmitter;
var emitter = new EventEmitter();

emitter.on('event', function () {
  emitter.emit('event');
});

emitter.emit('event');

nextTick can't really help:

var EventEmitter = require('events').EventEmitter;
var emitter = new EventEmitter();

emitter.on('event', function () {
  process.nextTick(function () {
    emitter.emit('event');
  });
});

emitter.emit('event');

Something like this happens in your case. When you use push synchronously in _read, you say "the stream is always readable". When you use readable event like that (read()), you say "as soon as stream as readable, give me everything". As you can see together these two statements mean that the process should be blocked forever, but as recursion is involved it causes stack overflow.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

4 participants