stream: wait for push writer end fallback to drain · nodejs/node@45780df · GitHub
Skip to content

Commit 45780df

Browse files
trivikraduh95
authored andcommitted
stream: wait for push writer end fallback to drain
When endSync() returns -1 after buffered writes, a follow-up end() should stay pending until the readable side drains the queued data. Do not make duplex channel close() wait for that drain, since close() only needs to signal EOF to the peer. Waiting there can deadlock when the peer starts reading only after close() resolves. Fixes: #63502 Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com> Assisted-by: openai:gpt-5.5 PR-URL: #63503 Backport-PR-URL: #64675 Fixes: #63502 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
1 parent 217b495 commit 45780df

3 files changed

Lines changed: 30 additions & 7 deletions

File tree

lib/internal/streams/iter/duplex.js

Lines changed: 2 additions & 6 deletions

lib/internal/streams/iter/push.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,10 @@ class PushQueue {
274274
if (this.#writerState === 'errored') {
275275
return -2; // Signal to reject with stored error
276276
}
277-
if (this.#writerState === 'closing' || this.#writerState === 'closed') {
277+
if (this.#writerState === 'closing') {
278+
return -3; // Signal to PushWriter: wait for drain to complete
279+
}
280+
if (this.#writerState === 'closed') {
278281
return this.#bytesWritten; // Idempotent
279282
}
280283

@@ -636,6 +639,10 @@ class PushWriter {
636639
if (result === -3) {
637640
// Closing: buffer has data, create deferred promise that resolves
638641
// when consumer drains past the end sentinel
642+
const pendingEndPromise = this.#queue.pendingEndPromise;
643+
if (pendingEndPromise !== null) {
644+
return pendingEndPromise;
645+
}
639646
const { promise, resolve, reject } = PromiseWithResolvers();
640647
this.#queue.setPendingEnd({ __proto__: null, promise, resolve, reject });
641648
return promise;

test/parallel/test-stream-iter-push-writer.js

Lines changed: 20 additions & 0 deletions

0 commit comments

Comments
 (0)