Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

finish event of stream.Writable is not expectedly emitted #11121

Closed
cynron opened this issue Feb 2, 2017 · 7 comments
Closed

finish event of stream.Writable is not expectedly emitted #11121

cynron opened this issue Feb 2, 2017 · 7 comments
Labels
stream Issues and PRs related to the stream subsystem.

Comments

@cynron
Copy link
Contributor

cynron commented Feb 2, 2017

  • Version: v8.0.0-pre/master branch, v6.9.5
  • Subsystem: stream.Writable

Hi,

If _writableState.corked > 0 and _writev callback with an error, after calling writable.end(), finish event is not emitted.

Test Case:

const stream = require('stream');

const writable = new stream.Writable();

writable._write = (chunks, encoding, cb) => {
  cb(new Error('write test error'));
};

writable._writev = (chunks, cb) => {
  cb(new Error('writev test error'));
};

writable.on('finish', () => {
  console.error('finish'); /* it should print "finish", but not */
});

writable.on('prefinish', () => {
  console.error('prefinish');
});

writable.on('error', (er) => {
  console.error('error');
});

writable.cork();
writable.write('test');

setTimeout(function() {
    writable.end('test');
}, 10);

In onwriteError, finishMaybe should also be checked. a test patch for master works:

diff --git a/lib/_stream_writable.js b/lib/_stream_writable.js
index eedeb56..ccda379 100644
--- a/lib/_stream_writable.js
+++ b/lib/_stream_writable.js
@@ -330,9 +330,14 @@ function doWrite(stream, state, writev, len, chunk, encoding, cb) {
 function onwriteError(stream, state, sync, er, cb) {
   --state.pendingcb;
   if (sync)
-    process.nextTick(cb, er);
+    process.nextTick(after, er);
   else
+    after(er);
+
+  function after(er) {
     cb(er);
+    finishMaybe(stream, state);
+  }

   stream._writableState.errorEmitted = true;
   stream.emit('error', er);

Please confirm whether it is a bug? make a PR for this?

Thanks!

@addaleax addaleax added the stream Issues and PRs related to the stream subsystem. label Feb 2, 2017
@cjihrig
Copy link
Contributor

cjihrig commented Feb 2, 2017

I'm not sure if this is a bug. You could probably make a case both ways. If we don't end up making a code change as a result of this issue, we should at least update the documentation.

@cynron
Copy link
Contributor Author

cynron commented Feb 3, 2017

Another testcase

finish is not emitted

// async_write.js
const stream = require('stream');
const writable = new stream.Writable();

writable._write = (chunks, encoding, cb) => {
  setTimeout(function() {
    cb(new Error('write test error'));
  }, 0); // _write async, defer callback
};

writable.on('finish', () => {
    console.error('finish'); // finish is not emitted
});

writable.on('error', (er) => {
    console.error('error');
});

writable.end('test');

finish is emitted

// sync_write.js
const stream = require('stream');
const writable = new stream.Writable();

writable._write = (chunks, encoding, cb) => {
  cb(new Error('write test error'));  // _write sync, callback immediately
};

writable.on('finish', () => {
    console.error('finish'); // finish is emitted 
});

writable.on('error', (er) => {
    console.error('error');
});
writable.end('test');

their behavior is inconsistent, after error occured,finish event should be either always emitted or never emitted. I think we should make it consistent and update the documentation to clarify this

@cjihrig
Copy link
Contributor

cjihrig commented Feb 3, 2017

We should probably be consistent. cc: @nodejs/streams

@mcollina
Copy link
Member

mcollina commented Feb 3, 2017

@cynron would you like to fire a PR? I think this is an actual bug, good find.
I'm not 100% sure of the fix, but we can work on it!

@mafintosh what do you think?

@cynron
Copy link
Contributor Author

cynron commented Feb 4, 2017

@mcollina I'm sorry I don't know which is expected, always emitted or never emitted?

@mcollina
Copy link
Member

mcollina commented Feb 4, 2017

@cynron I think it should emit 'finish'.

mcollina added a commit to mcollina/node that referenced this issue May 25, 2017
In Writable, 'finish' was not emitted when using writev() and
cork() in the event of an Error during the write. This commit
makes it consistent with the write() path, which emits 'finish'.

Fixes: nodejs#11121
@mcollina
Copy link
Member

Fixed in b153420.

mcollina added a commit that referenced this issue May 26, 2017
In Writable, 'finish' was not emitted when using writev() and
cork() in the event of an Error during the write. This commit
makes it consistent with the write() path, which emits 'finish'.

Fixes: #11121
PR-URL: #13195
Reviewed-By: Jeremiah Senkpiel <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Calvin Metcalf <[email protected]>
Reviewed-By: Colin Ihrig <[email protected]>
jasnell pushed a commit that referenced this issue May 28, 2017
In Writable, 'finish' was not emitted when using writev() and
cork() in the event of an Error during the write. This commit
makes it consistent with the write() path, which emits 'finish'.

Fixes: #11121
PR-URL: #13195
Reviewed-By: Jeremiah Senkpiel <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Calvin Metcalf <[email protected]>
Reviewed-By: Colin Ihrig <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stream Issues and PRs related to the stream subsystem.
Projects
None yet
Development

No branches or pull requests

4 participants