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

Non deterministic behavior for failing executables #10199

Closed
LittleHelicase opened this issue Dec 9, 2016 · 1 comment
Closed

Non deterministic behavior for failing executables #10199

LittleHelicase opened this issue Dec 9, 2016 · 1 comment
Labels
question Issues that look for answers.

Comments

@LittleHelicase
Copy link

LittleHelicase commented Dec 9, 2016

  • Version: v.6.9.1 & 7.2.0
  • Platform: Linux 4.4.0-51-generic Is V8 the best JS engine today? #72-Ubuntu SMP Thu Nov 24 18:29:54 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
  • Subsystem: child_process

When running processes with e.g. child_process.exec it is possible to write into the stdin stream via write.

var child_process = require('child_process')
var proc = child_process.exec('grep')
proc.stdin.write('abc')

I noticed that if the program (here grep) stops "fast enough" the write will throw an exception:

events.js:160
      throw er; // Unhandled 'error' event
      ^

Error: write EPIPE
    at exports._errnoException (util.js:1026:11)
    at WriteWrap.afterWrite (net.js:799:14)

This exception is not thrown by stdin.write directly. It seems that it is thrown in another event-loop iteration. It is not possible to catch this exception.

try {
  proc.stdin.write('abc')
} catch (err) {
  console.log('already closed')
}

Will not work. I tried to check the property stdin.destroyed but it seems that the value of destroyed is updated in the next event loop iteration. So it is not possible to prevent the problem with

if (!proc.stdin.destroyed) {
    proc.stdin.write('abc')
}

The only solution I found is using setTimeout to make sure that the event loop runs at least once before checking the .destroyed value, e.g.:

setTimeout(() => {
  if (!proc.stdin.destroyed) {
    proc.stdin.write('abc')
  }
}, 10)

I looked into the documentation of exec and spawn and I found that it is possible to explicitly specify the input stream for the spawned process via options.stdio and with this I could probably pipe the input into the stream before starting the process.
But it seems to me, that this problem can arise whenever write is called at the wrong time. Is this behavior intended and if so, how could I prevent the exception or at least catch it?

If you want to test it you can simply use the following C program that fails very fast

int main () { return 1; }

I had the problem with grep initially on a new fast PC. With the above C program the problem was reproducible on all machines.

@sam-github
Copy link
Contributor

write doesn't throw exceptions, use the error event, as suggested by the message // Unhandled 'error' event: https://nodejs.org/api/stream.html#stream_event_error

@sam-github sam-github added the question Issues that look for answers. label Dec 9, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Issues that look for answers.
Projects
None yet
Development

No branches or pull requests

2 participants