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

This commit is contained in:
Trent Mick 2012-11-04 22:11:55 -08:00
parent 7166772533
commit 69285c7a79
2 changed files with 37 additions and 13 deletions

View file

@ -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 file

@ -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);
}
}
dtrace.stderr.pipe(process.stderr);
dtrace.stderr.on('end', countdownToFinish);
dtrace.stderr.on('end', countdownToFinish);
dtrace.on('exit', countdownToFinish);
}
callback(code);
});
}