microsoft/vscode-react-native

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
4cd259621ddfbd348fade892a2f3ee87fd1924c5

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/common/node/childProcess.ts

191lines · 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";
ce5e88eeYuri Skorokhodov5 years ago5import { ErrorHelper } from "../error/errorHelper";
6import { InternalErrorCode } from "../error/internalErrorCode";
4bb0956eRedMickey5 years ago7import { notNullOrUndefined } from "../utils";
8import { kill } from "process";
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;
42}
43
44export class ChildProcess {
88246fe9Meena Kunnathur Balakrishnan10 years ago45public static ERROR_TIMEOUT_MILLISECONDS = 300;
6f8b71fedigeff10 years ago46private childProcess: typeof nodeChildProcess;
aab2095edigeff10 years ago47
ce5e88eeYuri Skorokhodov5 years ago48constructor({ childProcess = nodeChildProcess } = {}) {
aab2095edigeff10 years ago49this.childProcess = childProcess;
50}
51
ce5e88eeYuri Skorokhodov5 years ago52public exec(command: string, options: IExecOptions = {}): Promise<IExecResult> {
53let outcome: Promise<string>;
54let process: nodeChildProcess.ChildProcess;
34472878RedMickey5 years ago55return new Promise<IExecResult>(resolveRes => {
ce5e88eeYuri Skorokhodov5 years ago56outcome = new Promise<string>((resolve, reject) => {
34472878RedMickey5 years ago57process = this.childProcess.exec(
58command,
59options,
60// eslint-disable-next-line @typescript-eslint/no-unused-vars
61(error: Error, stdout: string, stderr: string) => {
ce5e88eeYuri Skorokhodov5 years ago62if (error) {
34472878RedMickey5 years ago63reject(
64ErrorHelper.getNestedError(
65error,
66InternalErrorCode.CommandFailed,
67command,
68),
69);
ce5e88eeYuri Skorokhodov5 years ago70} else {
71resolve(stdout);
72}
34472878RedMickey5 years ago73},
74);
75});
76resolveRes({ process: process, outcome: outcome });
3fb37ad5unknown10 years ago77});
78}
79
0d77292aJiglioNero4 years ago80public async execToString(command: string, options: IExecOptions = {}): Promise<string> {
81const execResult = await this.exec(command, options);
82const stdout = await execResult.outcome;
83return stdout.toString();
3fb37ad5unknown10 years ago84}
85
34472878RedMickey5 years ago86public execFileSync(
87command: string,
88args: string[] = [],
89options: IExecOptions = {},
90): Buffer | string {
b3753d4eRedMickey6 years ago91return this.childProcess.execFileSync(command, args, options);
92}
93
34472878RedMickey5 years ago94public spawn(
95command: string,
96args: string[] = [],
97options: ISpawnOptions = {},
98showStdOutputsOnError: boolean = false,
99): ISpawnResult {
9596aa53digeff10 years ago100const spawnedProcess = this.childProcess.spawn(command, args, options);
ce5e88eeYuri Skorokhodov5 years ago101let outcome: Promise<void> = new Promise((resolve, reject) => {
102spawnedProcess.once("error", (error: any) => {
103reject(error);
104});
105
dd8375caJiglioNero5 years ago106const stderrChunks: string[] = [];
107const stdoutChunks: string[] = [];
108
34472878RedMickey5 years ago109spawnedProcess.stderr.on("data", data => {
dd8375caJiglioNero5 years ago110stderrChunks.push(data.toString());
111});
112
34472878RedMickey5 years ago113spawnedProcess.stdout.on("data", data => {
dd8375caJiglioNero5 years ago114stdoutChunks.push(data.toString());
115});
116
ce5e88eeYuri Skorokhodov5 years ago117spawnedProcess.once("exit", (code: number) => {
118if (code === 0) {
119resolve();
120} else {
121const commandWithArgs = command + " " + args.join(" ");
dd8375caJiglioNero5 years ago122if (showStdOutputsOnError) {
123let details = "";
124if (stdoutChunks.length > 0) {
34472878RedMickey5 years ago125details = details.concat(
126`\n\tSTDOUT: ${stdoutChunks[stdoutChunks.length - 1]}`,
127);
dd8375caJiglioNero5 years ago128}
129if (stderrChunks.length > 0) {
130details = details.concat(`\n\tSTDERR: ${stderrChunks.join("\n\t")}`);
131}
132if (details === "") {
133details = "STDOUT and STDERR are empty!";
134}
34472878RedMickey5 years ago135reject(
136ErrorHelper.getInternalError(
137InternalErrorCode.CommandFailedWithDetails,
138commandWithArgs,
139details,
140),
141);
142} else {
143reject(
144ErrorHelper.getInternalError(
145InternalErrorCode.CommandFailed,
146commandWithArgs,
147code,
148),
149);
dd8375caJiglioNero5 years ago150}
ce5e88eeYuri Skorokhodov5 years ago151}
152});
3fb37ad5unknown10 years ago153});
c3a987a7Meena Kunnathur Balakrishnan10 years ago154return {
ce5e88eeYuri Skorokhodov5 years ago155spawnedProcess: spawnedProcess,
156stdin: spawnedProcess.stdin,
157stdout: spawnedProcess.stdout,
158stderr: spawnedProcess.stderr,
159outcome: outcome,
34472878RedMickey5 years ago160};
c3a987a7Meena Kunnathur Balakrishnan10 years ago161}
4bb0956eRedMickey5 years ago162
163// Kills any orphaned Instruments processes belonging to the user.
164//
165// In some cases, we've seen interactions between Instruments and the iOS
166// simulator that cause hung instruments and DTServiceHub processes. If
167// enough instances pile up, the host machine eventually becomes
168// unresponsive. Until the underlying issue is resolved, manually kill any
169// orphaned instances (where the parent process has died and PPID is 1)
170// before launching another instruments run.
171public async killOrphanedInstrumentsProcesses(): Promise<void> {
172const result = await this.execToString("ps -e -o user,ppid,pid,comm");
173if (result) {
174result
175.split("\n")
176.filter(notNullOrUndefined)
177.map(a => /^(\S+)\s+1\s+(\d+)\s+(.+)$/.exec(a))
178.filter(notNullOrUndefined)
179.filter(m => m[1] === process.env.USER)
180.filter(
181m =>
182m[3] && ["/instruments", "/DTServiceHub"].some(name => m[3].endsWith(name)),
183)
184.forEach(m => {
185const pid = m[2];
186console.debug(`Killing orphaned Instruments process: ${pid}`);
187kill(parseInt(pid, 10), "SIGKILL");
188});
189}
190}
3fb37ad5unknown10 years ago191}