microsoft/vscode-react-native

Public

mirrored from https://github.com/microsoft/vscode-react-nativeAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
remove-unused-debugging-code

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

src/common/node/childProcess.ts

200lines · modeblame

a31b007cunknown10 years ago1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for details.
3
6f8b71fedigeff10 years ago4import * as nodeChildProcess from "child_process";
09f6024fHeniker4 years ago5import { kill } from "process";
ce5e88eeYuri Skorokhodov5 years ago6import { ErrorHelper } from "../error/errorHelper";
7import { InternalErrorCode } from "../error/internalErrorCode";
4bb0956eRedMickey5 years ago8import { notNullOrUndefined } from "../utils";
3fb37ad5unknown10 years ago9
c7f1165cdigeff10 years ago10// Uncomment the following lines to record all spawned processes executions
3c172a05Artem Egorov8 years ago11// import {Recorder} from "../../../test/resources/processExecution/recorder";
c7f1165cdigeff10 years ago12// Recorder.installGlobalRecorder();
13
3fb37ad5unknown10 years ago14export interface IExecResult {
6f8b71fedigeff10 years ago15process: nodeChildProcess.ChildProcess;
ce5e88eeYuri Skorokhodov5 years ago16outcome: Promise<string>;
3fb37ad5unknown10 years ago17}
18
45944d15Meena Kunnathur Balakrishnan10 years ago19export interface ISpawnResult {
6f8b71fedigeff10 years ago20spawnedProcess: nodeChildProcess.ChildProcess;
5b0582f3digeff10 years ago21stdin: NodeJS.WritableStream;
22stdout: NodeJS.ReadableStream;
23stderr: NodeJS.ReadableStream;
ce5e88eeYuri Skorokhodov5 years ago24outcome: Promise<void>;
45944d15Meena Kunnathur Balakrishnan10 years ago25}
26
3fb37ad5unknown10 years ago27interface IExecOptions {
28cwd?: string;
29stdio?: any;
30env?: any;
31encoding?: string;
32timeout?: number;
33maxBuffer?: number;
34killSignal?: string;
35}
36
37interface ISpawnOptions {
38cwd?: string;
39stdio?: any;
40env?: any;
41detached?: boolean;
77e86943lexie0111 years ago42shell?: boolean;
3fb37ad5unknown10 years ago43}
44
45export class ChildProcess {
88246fe9Meena Kunnathur Balakrishnan10 years ago46public static ERROR_TIMEOUT_MILLISECONDS = 300;
6f8b71fedigeff10 years ago47private childProcess: typeof nodeChildProcess;
aab2095edigeff10 years ago48
ce5e88eeYuri Skorokhodov5 years ago49constructor({ childProcess = nodeChildProcess } = {}) {
aab2095edigeff10 years ago50this.childProcess = childProcess;
51}
52
ce5e88eeYuri Skorokhodov5 years ago53public exec(command: string, options: IExecOptions = {}): Promise<IExecResult> {
54let outcome: Promise<string>;
55let process: nodeChildProcess.ChildProcess;
34472878RedMickey5 years ago56return new Promise<IExecResult>(resolveRes => {
ce5e88eeYuri Skorokhodov5 years ago57outcome = new Promise<string>((resolve, reject) => {
34472878RedMickey5 years ago58process = this.childProcess.exec(
59command,
60options,
61// eslint-disable-next-line @typescript-eslint/no-unused-vars
176f99c8ConnorQi013 months ago62(
63error: nodeChildProcess.ExecException | null,
64stdout: string | Buffer,
65stderr: string | Buffer,
66) => {
ce5e88eeYuri Skorokhodov5 years ago67if (error) {
34472878RedMickey5 years ago68reject(
69ErrorHelper.getNestedError(
70error,
71InternalErrorCode.CommandFailed,
72command,
73),
74);
ce5e88eeYuri Skorokhodov5 years ago75} else {
176f99c8ConnorQi013 months ago76resolve(stdout.toString());
ce5e88eeYuri Skorokhodov5 years ago77}
34472878RedMickey5 years ago78},
79);
80});
09f6024fHeniker4 years ago81resolveRes({ process, outcome });
3fb37ad5unknown10 years ago82});
83}
84
0d77292aJiglioNero4 years ago85public async execToString(command: string, options: IExecOptions = {}): Promise<string> {
86const execResult = await this.exec(command, options);
87const stdout = await execResult.outcome;
88return stdout.toString();
3fb37ad5unknown10 years ago89}
90
34472878RedMickey5 years ago91public execFileSync(
92command: string,
93args: string[] = [],
94options: IExecOptions = {},
95): Buffer | string {
b3753d4eRedMickey6 years ago96return this.childProcess.execFileSync(command, args, options);
97}
98
34472878RedMickey5 years ago99public spawn(
100command: string,
101args: string[] = [],
102options: ISpawnOptions = {},
103showStdOutputsOnError: boolean = false,
104): ISpawnResult {
77e86943lexie0111 years ago105const spawnedProcess = this.childProcess.spawn(
106command,
107args,
108Object.assign({}, options, { shell: true }),
109);
09f6024fHeniker4 years ago110const outcome: Promise<void> = new Promise((resolve, reject) => {
ce5e88eeYuri Skorokhodov5 years ago111spawnedProcess.once("error", (error: any) => {
112reject(error);
113});
114
dd8375caJiglioNero5 years ago115const stderrChunks: string[] = [];
116const stdoutChunks: string[] = [];
117
34472878RedMickey5 years ago118spawnedProcess.stderr.on("data", data => {
dd8375caJiglioNero5 years ago119stderrChunks.push(data.toString());
120});
121
34472878RedMickey5 years ago122spawnedProcess.stdout.on("data", data => {
dd8375caJiglioNero5 years ago123stdoutChunks.push(data.toString());
124});
125
ce5e88eeYuri Skorokhodov5 years ago126spawnedProcess.once("exit", (code: number) => {
127if (code === 0) {
128resolve();
129} else {
09f6024fHeniker4 years ago130const commandWithArgs = `${command} ${args.join(" ")}`;
dd8375caJiglioNero5 years ago131if (showStdOutputsOnError) {
132let details = "";
133if (stdoutChunks.length > 0) {
34472878RedMickey5 years ago134details = details.concat(
135`\n\tSTDOUT: ${stdoutChunks[stdoutChunks.length - 1]}`,
136);
dd8375caJiglioNero5 years ago137}
138if (stderrChunks.length > 0) {
139details = details.concat(`\n\tSTDERR: ${stderrChunks.join("\n\t")}`);
140}
141if (details === "") {
142details = "STDOUT and STDERR are empty!";
143}
34472878RedMickey5 years ago144reject(
145ErrorHelper.getInternalError(
146InternalErrorCode.CommandFailedWithDetails,
147commandWithArgs,
148details,
149),
150);
151} else {
152reject(
153ErrorHelper.getInternalError(
154InternalErrorCode.CommandFailed,
155commandWithArgs,
156code,
157),
158);
dd8375caJiglioNero5 years ago159}
ce5e88eeYuri Skorokhodov5 years ago160}
161});
3fb37ad5unknown10 years ago162});
c3a987a7Meena Kunnathur Balakrishnan10 years ago163return {
09f6024fHeniker4 years ago164spawnedProcess,
ce5e88eeYuri Skorokhodov5 years ago165stdin: spawnedProcess.stdin,
166stdout: spawnedProcess.stdout,
167stderr: spawnedProcess.stderr,
09f6024fHeniker4 years ago168outcome,
34472878RedMickey5 years ago169};
c3a987a7Meena Kunnathur Balakrishnan10 years ago170}
4bb0956eRedMickey5 years ago171
172// Kills any orphaned Instruments processes belonging to the user.
173//
174// In some cases, we've seen interactions between Instruments and the iOS
175// simulator that cause hung instruments and DTServiceHub processes. If
176// enough instances pile up, the host machine eventually becomes
177// unresponsive. Until the underlying issue is resolved, manually kill any
178// orphaned instances (where the parent process has died and PPID is 1)
179// before launching another instruments run.
180public async killOrphanedInstrumentsProcesses(): Promise<void> {
181const result = await this.execToString("ps -e -o user,ppid,pid,comm");
182if (result) {
183result
184.split("\n")
185.filter(notNullOrUndefined)
186.map(a => /^(\S+)\s+1\s+(\d+)\s+(.+)$/.exec(a))
187.filter(notNullOrUndefined)
188.filter(m => m[1] === process.env.USER)
189.filter(
190m =>
191m[3] && ["/instruments", "/DTServiceHub"].some(name => m[3].endsWith(name)),
192)
193.forEach(m => {
194const pid = m[2];
195console.debug(`Killing orphaned Instruments process: ${pid}`);
196kill(parseInt(pid, 10), "SIGKILL");
197});
198}
199}
3fb37ad5unknown10 years ago200}