diff options
Diffstat (limited to 'lib/internal/process.js')
| -rw-r--r-- | lib/internal/process.js | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/lib/internal/process.js b/lib/internal/process.js index c435c2e871..5b6e56fa9a 100644 --- a/lib/internal/process.js +++ b/lib/internal/process.js @@ -145,7 +145,69 @@ function setupKillAndExit() { process._exiting = true; process.emit('exit', process.exitCode || 0); } + + // Flush stdio streams prior to exit. + // `flushSync` not present if stream redirected to file in shell. + flushSync(process.stdout); + flushSync(process.stderr); + process.reallyExit(process.exitCode || 0); + + function flushSync(stream) { + + // Behavior of this function outside of process.exit() is undefined + // due to the following factors: + // * Stream fd may be blocking after this call. + // * In the event of an incomplete flush pending buffered write + // requests may be truncated. + // * No return code. + + if (stream._writev) + return; + + var handle = stream._handle; + if (!handle || !handle.flushSync) + return; + + var fd = handle.fd; + if (typeof fd !== 'number' || fd < 0) + return; + + // FIXME: late module resolution avoids cross require problem + const fs = require('fs'); + + const Buffer = require('buffer'); + + // Queued libuv writes must be flushed first. + // Note: fd will set to blocking after handle.flushSync() + if (handle.flushSync() !== 0) { + // bad fd or write queue for libuv stream not entirely flushed + return; + } + + // then the queued stream chunks can be flushed + var state = stream._writableState; + var entry = state.bufferedRequest; + while (entry) { + var chunk = entry.chunk; + if (!(chunk instanceof Buffer)) { + chunk = Buffer.from(chunk, entry.encoding); + } + // Note: fd is blocking at this point + var written = fs.writeSync(fd, chunk, 0, chunk.length); + if (written !== chunk.length) { + // stream chunk not flushed entirely - stop writing. + // FIXME: buffered request queue should be repaired here + // rather than being truncated after loop break + break; + } + entry = entry.next; + } + + state.bufferedRequestCount = 0; + state.bufferedRequest = null; + state.lastBufferedRequest = null; + } }; process.kill = function(pid, sig) { |
