Skip to content

EFAULT error in process.stdout.write(data, 'hex') #8251

Closed
@kotarondo

Description

@kotarondo
  • 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.

Metadata

Metadata

Assignees

Labels

confirmed-bugIssues with confirmed bugs.netIssues and PRs related to the net subsystem.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions