microsoft/vscode-react-native

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
run-test-smoke1

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/common/node/childProcess.ts

196lines · 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
62(error: Error, stdout: string, stderr: string) => {
ce5e88eeYuri Skorokhodov5 years ago63if (error) {
34472878RedMickey5 years ago64reject(
65ErrorHelper.getNestedError(
66error,
67InternalErrorCode.CommandFailed,
68command,
69),
70);
ce5e88eeYuri Skorokhodov5 years ago71} else {
72resolve(stdout);
73}
34472878RedMickey5 years ago74},
75);
76});
09f6024fHeniker4 years ago77resolveRes({ process, outcome });
3fb37ad5unknown10 years ago78});
79}
80
0d77292aJiglioNero4 years ago81public async execToString(command: string, options: IExecOptions = {}): Promise<string> {
82const execResult = await this.exec(command, options);
83const stdout = await execResult.outcome;
84return stdout.toString();
3fb37ad5unknown10 years ago85}
86
34472878RedMickey5 years ago87public execFileSync(
88command: string,
89args: string[] = [],
90options: IExecOptions = {},
91): Buffer | string {
b3753d4eRedMickey6 years ago92return this.childProcess.execFileSync(command, args, options);
93}
94
34472878RedMickey5 years ago95public spawn(
96command: string,
97args: string[] = [],
98options: ISpawnOptions = {},
99showStdOutputsOnError: boolean = false,
100): ISpawnResult {
77e86943lexie0111 years ago101const spawnedProcess = this.childProcess.spawn(
102command,
103args,
104Object.assign({}, options, { shell: true }),
105);
09f6024fHeniker4 years ago106const outcome: Promise<void> = new Promise((resolve, reject) => {
ce5e88eeYuri Skorokhodov5 years ago107spawnedProcess.once("error", (error: any) => {
108reject(error);
109});
110
dd8375caJiglioNero5 years ago111const stderrChunks: string[] = [];
112const stdoutChunks: string[] = [];
113
34472878RedMickey5 years ago114spawnedProcess.stderr.on("data", data => {
dd8375caJiglioNero5 years ago115stderrChunks.push(data.toString());
116});
117
34472878RedMickey5 years ago118spawnedProcess.stdout.on("data", data => {
dd8375caJiglioNero5 years ago119stdoutChunks.push(data.toString());
120});
121
ce5e88eeYuri Skorokhodov5 years ago122spawnedProcess.once("exit", (code: number) => {
123if (code === 0) {
124resolve();
125} else {
09f6024fHeniker4 years ago126const commandWithArgs = `${command} ${args.join(" ")}`;
dd8375caJiglioNero5 years ago127if (showStdOutputsOnError) {
128let details = "";
129if (stdoutChunks.length > 0) {
34472878RedMickey5 years ago130details = details.concat(
131`\n\tSTDOUT: ${stdoutChunks[stdoutChunks.length - 1]}`,
132);
dd8375caJiglioNero5 years ago133}
134if (stderrChunks.length > 0) {
135details = details.concat(`\n\tSTDERR: ${stderrChunks.join("\n\t")}`);
136}
137if (details === "") {
138details = "STDOUT and STDERR are empty!";
139}
34472878RedMickey5 years ago140reject(
141ErrorHelper.getInternalError(
142InternalErrorCode.CommandFailedWithDetails,
143commandWithArgs,
144details,
145),
146);
147} else {
148reject(
149ErrorHelper.getInternalError(
150InternalErrorCode.CommandFailed,
151commandWithArgs,
152code,
153),
154);
dd8375caJiglioNero5 years ago155}
ce5e88eeYuri Skorokhodov5 years ago156}
157});
3fb37ad5unknown10 years ago158});
c3a987a7Meena Kunnathur Balakrishnan10 years ago159return {
09f6024fHeniker4 years ago160spawnedProcess,
ce5e88eeYuri Skorokhodov5 years ago161stdin: spawnedProcess.stdin,
162stdout: spawnedProcess.stdout,
163stderr: spawnedProcess.stderr,
09f6024fHeniker4 years ago164outcome,
34472878RedMickey5 years ago165};
c3a987a7Meena Kunnathur Balakrishnan10 years ago166}
4bb0956eRedMickey5 years ago167
168// Kills any orphaned Instruments processes belonging to the user.
169//
170// In some cases, we've seen interactions between Instruments and the iOS
171// simulator that cause hung instruments and DTServiceHub processes. If
172// enough instances pile up, the host machine eventually becomes
173// unresponsive. Until the underlying issue is resolved, manually kill any
174// orphaned instances (where the parent process has died and PPID is 1)
175// before launching another instruments run.
176public async killOrphanedInstrumentsProcesses(): Promise<void> {
177const result = await this.execToString("ps -e -o user,ppid,pid,comm");
178if (result) {
179result
180.split("\n")
181.filter(notNullOrUndefined)
182.map(a => /^(\S+)\s+1\s+(\d+)\s+(.+)$/.exec(a))
183.filter(notNullOrUndefined)
184.filter(m => m[1] === process.env.USER)
185.filter(
186m =>
187m[3] && ["/instruments", "/DTServiceHub"].some(name => m[3].endsWith(name)),
188)
189.forEach(m => {
190const pid = m[2];
191console.debug(`Killing orphaned Instruments process: ${pid}`);
192kill(parseInt(pid, 10), "SIGKILL");
193});
194}
195}
3fb37ad5unknown10 years ago196}