Skip to content

Commit

Permalink
stream: do not deadlock duplexpair
Browse files Browse the repository at this point in the history
If nothing is buffered then _read will not be called and the
callback will not be invoked, effectivly deadlocking.

Fixes: #29758

PR-URL: #29836
Refs: #29649
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Minwoo Jung <minwoo@nodesource.com>
  • Loading branch information
ronag authored and BridgeAR committed Oct 9, 2019
1 parent e7f604f commit 6c75cc1
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 5 deletions.
4 changes: 3 additions & 1 deletion doc/api/stream.md
Original file line number Diff line number Diff line change
Expand Up @@ -2059,7 +2059,9 @@ when `_read()` is called again after it has stopped should it resume pushing
additional data onto the queue.

Once the `readable._read()` method has been called, it will not be called again
until the [`readable.push()`][stream-push] method is called.
until more data is pushed through the [`readable.push()`][stream-push] method.
Empty data such as empty buffers and strings will not cause `readable._read()`
to be called.

The `size` argument is advisory. For implementations where a "read" is a
single operation that returns data can use the `size` argument to determine how
Expand Down
8 changes: 6 additions & 2 deletions lib/internal/streams/duplexpair.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,12 @@ class DuplexSocket extends Duplex {
}

_write(chunk, encoding, callback) {
this[kOtherSide][kCallback] = callback;
this[kOtherSide].push(chunk);
if (chunk.length === 0) {
process.nextTick(callback);
} else {
this[kOtherSide].push(chunk);
this[kOtherSide][kCallback] = callback;
}
}

_final(callback) {
Expand Down
8 changes: 6 additions & 2 deletions test/common/duplexpair.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,12 @@ class DuplexSocket extends Duplex {
_write(chunk, encoding, callback) {
assert.notStrictEqual(this[kOtherSide], null);
assert.strictEqual(this[kOtherSide][kCallback], null);
this[kOtherSide][kCallback] = callback;
this[kOtherSide].push(chunk);
if (chunk.length === 0) {
process.nextTick(callback);
} else {
this[kOtherSide].push(chunk);
this[kOtherSide][kCallback] = callback;
}
}

_final(callback) {
Expand Down

0 comments on commit 6c75cc1

Please sign in to comment.