Permalink
Browse files

issue #54: fix stderr flushing of dtrace child proc (again)

  • Loading branch information...
trentm committed Nov 5, 2012
1 parent 7166772 commit 69285c7a79e1b6c1c0748f18a9cd41cbd4958098
Showing with 37 additions and 13 deletions.
  1. +3 −1 CHANGES.md
  2. +34 −12 bin/bunyan
View
@@ -2,7 +2,9 @@
## bunyan 0.16.4 (not yet released)
-(nothing yet)
+- issue #54: Ensure (again, see 0.16.2) that stderr from the dtrace child
+ process (when using `bunyan -p PID`) gets through. There had been a race
+ between exiting bunyan and the flushing of the dtrace process' stderr.
## bunyan 0.16.3
View
@@ -15,6 +15,8 @@ var fs = require('fs');
var warn = console.warn;
var spawn = require('child_process').spawn;
+var nodeSpawnSupportsStdio = (Number(process.version.split('.')[1]) >= 8);
+
//---- globals and constants
@@ -907,13 +909,19 @@ function processPid(opts, stylize, callback) {
var leftover = ""; // Left-over partial line from last chunk.
var argv = ['dtrace', '-Z', '-x', 'strsize=4k', '-qn',
format('bunyan%d:::log-*{printf("%s", copyinstr(arg0))}', opts.pid)];
- var dtrace = spawn(argv[0], argv.slice(1));
- child = dtrace; // intentionall global
+ var dtrace = spawn(argv[0], argv.slice(1),
+ // Share the stderr handle to have error output come
+ // straight through. Only supported in v0.8+.
+ {stdio: ['pipe', 'pipe', process.stderr]});
+ child = dtrace; // intentionally global
- dtrace.stderr.setEncoding('utf8');
- dtrace.stderr.on('data', function (chunk) {
- process.stderr.write(chunk);
- });
+ function finish(code) {
+ if (leftover) {
+ handleLogLine(null, leftover, opts, stylize);
+ leftover = '';
+ }
+ callback(returnCode);
+ }
dtrace.stdout.setEncoding('utf8');
dtrace.stdout.on('data', function (chunk) {
@@ -932,13 +940,27 @@ function processPid(opts, stylize, callback) {
handleLogLine(null, lines[i], opts, stylize);
}
});
- dtrace.on('exit', function (code) {
- if (leftover) {
- handleLogLine(null, leftover, opts, stylize);
- leftover = '';
+
+ if (nodeSpawnSupportsStdio) {
+ dtrace.on('exit', finish);
+ } else {
+ // Fallback (for < v0.8) to pipe the dtrace process' stderr to this stderr.
+ // Wait for all of (1) process 'exit', (2) stderr 'end', and (2) stdout
+ // 'end' before returning to ensure all stderr is flushed (issue #54).
+ var returnCode = null;
+ var eventsRemaining = 3;
+ function countdownToFinish(code) {
+ returnCode = code;
+ eventsRemaining--;
+ if (eventsRemaining == 0) {
+ finish(returnCode);
+ }
}
- callback(code);
- });
+ dtrace.stderr.pipe(process.stderr);
+ dtrace.stderr.on('end', countdownToFinish);
+ dtrace.stderr.on('end', countdownToFinish);
+ dtrace.on('exit', countdownToFinish);
+ }
}

0 comments on commit 69285c7

Please sign in to comment.