提交 7eb84eff 编写于 作者: A Alex Dima

Remove stdFork since it is no longer used

上级 ad972a1d
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as path from 'path';
import * as os from 'os';
import * as net from 'net';
import * as cp from 'child_process';
import { getPathFromAmdModule } from 'vs/base/common/amd';
export interface IForkOpts {
cwd?: string;
env?: any;
encoding?: string;
execArgv?: string[];
}
function makeRandomHexString(length: number): string {
let chars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
let result = '';
for (let i = 0; i < length; i++) {
let idx = Math.floor(chars.length * Math.random());
result += chars[idx];
}
return result;
}
function generatePipeName(): string {
let randomName = 'vscode-std-' + makeRandomHexString(40);
if (process.platform === 'win32') {
return '\\\\.\\pipe\\' + randomName + '-sock';
}
// Mac/Unix: use socket file
return path.join(os.tmpdir(), randomName + '.sock');
}
function generatePatchedEnv(env: any, stdInPipeName: string, stdOutPipeName: string, stdErrPipeName: string): any {
// Set the two unique pipe names and the electron flag as process env
let newEnv: any = {};
for (let key in env) {
newEnv[key] = env[key];
}
newEnv['STDIN_PIPE_NAME'] = stdInPipeName;
newEnv['STDOUT_PIPE_NAME'] = stdOutPipeName;
newEnv['STDERR_PIPE_NAME'] = stdErrPipeName;
newEnv['ELECTRON_RUN_AS_NODE'] = '1';
return newEnv;
}
export function fork(modulePath: string, args: string[], options: IForkOpts, callback: (error: any, cp: cp.ChildProcess) => void): void {
let callbackCalled = false;
let resolve = (result: cp.ChildProcess) => {
if (callbackCalled) {
return;
}
callbackCalled = true;
callback(null, result);
};
let reject = (err: any) => {
if (callbackCalled) {
return;
}
callbackCalled = true;
callback(err, null);
};
// Generate three unique pipe names
let stdInPipeName = generatePipeName();
let stdOutPipeName = generatePipeName();
let stdErrPipeName = generatePipeName();
let newEnv = generatePatchedEnv(options.env || process.env, stdInPipeName, stdOutPipeName, stdErrPipeName);
let childProcess: cp.ChildProcess;
// Begin listening to stderr pipe
let stdErrServer = net.createServer((stdErrStream) => {
// From now on the childProcess.stderr is available for reading
childProcess.stderr = stdErrStream;
});
stdErrServer.listen(stdErrPipeName);
// Begin listening to stdout pipe
let stdOutServer = net.createServer((stdOutStream) => {
// The child process will write exactly one chunk with content `ready` when it has installed a listener to the stdin pipe
stdOutStream.once('data', (chunk: Buffer) => {
// The child process is sending me the `ready` chunk, time to connect to the stdin pipe
childProcess.stdin = <any>net.connect(stdInPipeName);
// From now on the childProcess.stdout is available for reading
childProcess.stdout = stdOutStream;
resolve(childProcess);
});
});
stdOutServer.listen(stdOutPipeName);
let serverClosed = false;
let closeServer = () => {
if (serverClosed) {
return;
}
serverClosed = true;
process.removeListener('exit', closeServer);
stdOutServer.close();
stdErrServer.close();
};
// Create the process
let bootstrapperPath = (getPathFromAmdModule(require, './stdForkStart.js'));
childProcess = cp.fork(bootstrapperPath, [modulePath].concat(args), {
silent: true,
cwd: options.cwd,
env: newEnv,
execArgv: options.execArgv
});
childProcess.once('error', (err: Error) => {
closeServer();
reject(err);
});
childProcess.once('exit', (err: Error) => {
closeServer();
reject(err);
});
// On vscode exit still close server #7758
process.once('exit', closeServer);
}
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const net = require('net');
const fs = require('fs');
// const stream = require('stream');
// const util = require('util');
var ENABLE_LOGGING = false;
var log = (function () {
if (!ENABLE_LOGGING) {
return function () { };
}
var isFirst = true;
var 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');
};
})();
var stdInPipeName = process.env['STDIN_PIPE_NAME'];
var stdOutPipeName = process.env['STDOUT_PIPE_NAME'];
var stdErrPipeName = process.env['STDERR_PIPE_NAME'];
log('STDIN_PIPE_NAME: ' + stdInPipeName);
log('STDOUT_PIPE_NAME: ' + stdOutPipeName);
log('STDERR_PIPE_NAME: ' + stdErrPipeName);
log('ELECTRON_RUN_AS_NODE: ' + process.env['ELECTRON_RUN_AS_NODE']);
// stdout redirection to named pipe
(function () {
log('Beginning stdout redirection...');
// Create a writing stream to the stdout pipe
var stdOutStream = net.connect(stdOutPipeName);
// unref stdOutStream to behave like a normal standard out
stdOutStream.unref();
// handle process.stdout
process.__defineGetter__('stdout', function () { return stdOutStream; });
// Create a writing stream to the stderr pipe
var stdErrStream = net.connect(stdErrPipeName);
// unref stdErrStream to behave like a normal standard out
stdErrStream.unref();
// handle process.stderr
process.__defineGetter__('stderr', function () { return stdErrStream; });
var fsWriteSyncString = function (fd, str, position, encoding) {
// fs.writeSync(fd, string[, position[, encoding]]);
var buf = Buffer.from(str, encoding || 'utf8');
return fsWriteSyncBuffer(fd, buf, 0, buf.length);
};
var fsWriteSyncBuffer = function (fd, buffer, off, len/* , position */) {
off = Math.abs(off | 0);
len = Math.abs(len | 0);
// fs.writeSync(fd, buffer, offset, length[, position]);
var 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');
}
var 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, ...) and fs.writeSync(2, ...)
var originalWriteSync = fs.writeSync;
fs.writeSync = function (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');
})();
// stdin redirection to named pipe
(function () {
// Begin listening to stdin pipe
var 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.');
// handle process.stdin
process.__defineGetter__('stdin', function () {
return stream;
});
// Remove myself from process.argv
process.argv.splice(1, 1);
// Load the actual program
var program = process.argv[1];
log('Loading program: ' + program);
// Unset the custom environmental variables that should not get inherited
delete process.env['STDIN_PIPE_NAME'];
delete process.env['STDOUT_PIPE_NAME'];
delete process.env['STDERR_PIPE_NAME'];
delete process.env['ELECTRON_RUN_AS_NODE'];
require(program);
log('Finished loading program.');
var stdinIsReferenced = true;
var timer = setInterval(function () {
var 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);
timer.unref();
});
server.listen(stdInPipeName, function () {
// signal via stdout that the parent process can now begin writing to stdin pipe
process.stdout.write('ready');
});
})();
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册