Description
- Version:6.4.0 (or lower versions)
- Platform: macosx (or any other unix/linux)
- Subsystem: none
summary
This test program stops with EFAULT error
when it is executed with piped stdout.
EFAULT error must not occur in writing to stdout.
It seems a bug in Node.js.
test.js:
var data = new Buffer(1000000).toString('hex');
function write_loop() {
while (process.stdout.write(data, 'hex'));
}
process.stdout.on('drain', write_loop);
write_loop();
function memory_pressure() {
var val = [];
for (var i = 0; i < 1000000; i++) {
val[i] = i;
}
return val;
}
setInterval(memory_pressure, 100);
detail
% node test.js | cat >/dev/null
events.js:160
throw er; // Unhandled 'error' event
^
Error: write EFAULT
at exports._errnoException (util.js:1026:11)
at WriteWrap.afterWrite (net.js:794:14)
- The stdout of 'node test.js' must be piped in order to result EFAULT error.
- 'hex' encoding is also needed.
- EFAULT error seldom occurs without memory_pressure.
possible cause
I found that error does not occur with this workaround code added.
var orig_writeBuffer = process.stdout._handle.writeBuffer;
process.stdout._handle.writeBuffer = function(req, b) {
req.keepReferenceForWorkaround = b;
orig_writeBuffer.call(this, req, b);
}
process.stdout._handle.writeBuffer actually is native-code
and it seems it assumes a reference of passed buffer is kept alive until write-completion.
In case of 'hex' encoding, passed buffer was created in
createWriteReq() in node/lib/net.js as follows:
default:
return handle.writeBuffer(req, Buffer.from(data, encoding));
So, this buffer can be garbage-collected if handler.writeBuffer does not keep the reference alive.
other information
handle.writeBuffer is used also in case of 'buffer' encoding,
but the passed buffer is stored in the request object
in Socket.prototype._writeGeneric() (node/lib/net.js) as follows:
if (data instanceof Buffer) {
req.buffer = data; // Keep reference alive.
enc = 'buffer';
} else {
enc = encoding;
}
err = createWriteReq(req, this._handle, data, enc);
So, in this case, EFALT error does not occur.