|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- /*---------------------------------------------------------------------------------------------
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
- let net = require('net');
- let fs = require('fs');
- let ENABLE_LOGGING = false;
- let log = (function () {
- if (!ENABLE_LOGGING) {
- return function () { }; // tslint:disable-line
- }
- let isFirst = true;
- let LOG_LOCATION = 'C:\\stdFork.log';
- return function log(str) {
- if (isFirst) {
- isFirst = false;
- fs.writeFileSync(LOG_LOCATION, str + '\n');
- return;
- }
- fs.appendFileSync(LOG_LOCATION, str + '\n');
- };
- })();
- let stdInPipeName = process.env['STDIN_PIPE_NAME']; // tslint:disable-line
- let stdOutPipeName = process.env['STDOUT_PIPE_NAME']; // tslint:disable-line
- let stdErrPipeName = process.env['STDERR_PIPE_NAME']; // tslint:disable-line
- log('STDIN_PIPE_NAME: ' + stdInPipeName);
- log('STDOUT_PIPE_NAME: ' + stdOutPipeName);
- log('STDERR_PIPE_NAME: ' + stdErrPipeName);
- (function () {
- log('Beginning stdout redirection...');
- // Create a writing stream to the stdout pipe
- let stdOutStream = net.connect(stdOutPipeName);
- // unref stdOutStream to behave like a normal standard out
- stdOutStream.unref();
- process.__defineGetter__('stdout', function () {
- return stdOutStream;
- });
- // Create a writing stream to the stderr pipe
- let stdErrStream = net.connect(stdErrPipeName);
- // unref stdErrStream to behave like a normal standard out
- stdErrStream.unref();
- process.__defineGetter__('stderr', function () {
- return stdErrStream;
- });
- let fsWriteSyncString = function (// tslint:disable-line
- fd, str, _position, encoding) {
- // fs.writeSync(fd, string[, position[, encoding]])
- let buf = Buffer.from(str, encoding || 'utf8');
- return fsWriteSyncBuffer(fd, buf, 0, buf.length); // tslint:disable-line
- };
- let fsWriteSyncBuffer = function (// tslint:disable-line
- fd, buffer, off, len) {
- off = Math.abs(off | 0);
- len = Math.abs(len | 0);
- // fs.writeSync(fd, buffer, offset, length[, position])
- let buffer_length = buffer.length;
- if (off > buffer_length) {
- throw new Error('offset out of bounds');
- }
- if (len > buffer_length) {
- throw new Error('length out of bounds');
- }
- if (((off + len) | 0) < off) {
- throw new Error('off + len overflow');
- }
- if (buffer_length - off < len) {
- // Asking for more than is left over in the buffer
- throw new Error('off + len > buffer.length');
- }
- let slicedBuffer = buffer;
- if (off !== 0 || len !== buffer_length) {
- slicedBuffer = buffer.slice(off, off + len);
- }
- if (fd === 1) {
- stdOutStream.write(slicedBuffer);
- }
- else {
- stdErrStream.write(slicedBuffer);
- }
- return slicedBuffer.length;
- };
- // handle fs.writeSync(1, ...)
- let originalWriteSync = fs.writeSync;
- fs.writeSync = function (// tslint:disable-line
- fd, data, _position, _encoding) {
- if (fd !== 1 && fd !== 2) {
- return originalWriteSync.apply(fs, arguments);
- }
- // usage:
- // fs.writeSync(fd, buffer, offset, length[, position])
- // OR
- // fs.writeSync(fd, string[, position[, encoding]])
- if (data instanceof Buffer) {
- return fsWriteSyncBuffer.apply(null, arguments);
- }
- // For compatibility reasons with fs.writeSync, writing null will write "null", etc
- if (typeof data !== 'string') {
- data += '';
- }
- return fsWriteSyncString.apply(null, arguments);
- };
- log('Finished defining process.stdout, process.stderr and fs.writeSync');
- })();
- (function () {
- // Begin listening to stdin pipe
- let server = net.createServer(function (stream) {
- // Stop accepting new connections, keep the existing one alive
- server.close();
- log('Parent process has connected to my stdin. All should be good now.');
- process.__defineGetter__('stdin', function () {
- return stream;
- });
- // Remove myself from process.argv
- process.argv.splice(1, 1);
- // Load the actual program
- let program = process.argv[1];
- log('Loading program: ' + program);
- // Unset the custom environmental variables that should not get inherited
- delete process.env['STDIN_PIPE_NAME']; // tslint:disable-line
- delete process.env['STDOUT_PIPE_NAME']; // tslint:disable-line
- delete process.env['STDERR_PIPE_NAME']; // tslint:disable-line
- require(program);
- log('Finished loading program.');
- let stdinIsReferenced = true;
- let timer = setInterval(function () {
- let listenerCount = stream.listeners('data').length +
- stream.listeners('end').length +
- stream.listeners('close').length +
- stream.listeners('error').length;
- // log('listenerCount: ' + listenerCount)
- if (listenerCount <= 1) {
- // No more "actual" listeners, only internal node
- if (stdinIsReferenced) {
- stdinIsReferenced = false;
- // log('unreferencing stream!!!')
- stream.unref();
- }
- }
- else {
- // There are "actual" listeners
- if (!stdinIsReferenced) {
- stdinIsReferenced = true;
- stream.ref();
- }
- }
- // log(
- // '' + stream.listeners('data').length +
- // ' ' + stream.listeners('end').length +
- // ' ' + stream.listeners('close').length +
- // ' ' + stream.listeners('error').length
- // )
- }, 1000);
- if (timer.unref) { // tslint:disable-line
- timer.unref(); // tslint:disable-line
- }
- });
- server.listen(stdInPipeName, function () {
- // signal via stdout that the parent process can now begin writing to stdin pipe
- process.stdout.write('ready');
- });
- })();
|