Skip to content

Check exit code #209

@fpoli

Description

@fpoli

The Viper IDE took its spawn function from this repository. In the process, they did some nice changes, among with a check of the exist code of the spawned process: viperproject/viper-ide#357. We should port the same check to this repository.

Relevant code:

export function spawn(
cmd: string,
args?: string[] | undefined,
{ options, onStdout, onStderr }: {
options?: childProcess.SpawnOptionsWithoutStdio;
onStdout?: ((data: string) => void);
onStderr?: ((data: string) => void);
} = {},
destructors?: Set<KillFunction>,
): Promise<Output> {
const description = `${cmd} ${args?.join(" ") ?? ""}`;
log(`Run command '${description}'`);
let stdout = "";
let stderr = "";
const start = process.hrtime();
const proc = childProcess.spawn(cmd, args, options);
const status: { killed: boolean } = { killed: false };
log(`Spawned PID: ${proc.pid}`);
// Register destructor
function killProc() {
if (!status.killed) {
status.killed = true;
// TODO: Try with SIGTERM before.
treeKill(proc.pid, "SIGKILL", (err) => {
if (err) {
log(`Failed to kill process tree of ${proc.pid}: ${err}`);
const succeeded = proc.kill("SIGKILL");
if (!succeeded) {
log(`Failed to kill process ${proc}.`);
}
} else {
log(`Process ${proc.pid} has been killed successfully.`);
}
});
} else {
log(`Process ${proc.pid} has already been killed.`);
}
}
if (destructors) {
destructors.add(killProc);
}
proc.stdout.on("data", (data) => {
stdout += data;
try {
onStdout?.(data);
} catch (e) {
log(`error in stdout handler for '${description}': ${e}`);
}
});
proc.stderr.on("data", (data) => {
stderr += data;
try {
onStderr?.(data);
} catch (e) {
log(`error in stderr handler for '${description}': ${e}`);
}
});
function printOutput(duration: Duration, code: number | null, signal: NodeJS.Signals | null) {
const durationSecMsg = (duration[0] + duration[1] / 1e9).toFixed(1);
log(`Output from '${description}' (${durationSecMsg}s):`);
log("┌──── Begin stdout ────┐");
log(stdout);
log("└──── End stdout ──────┘");
log("┌──── Begin stderr ────┐");
log(stderr);
log("└──── End stderr ──────┘");
log(`Exit code ${code}, signal ${signal}.`);
}
return new Promise((resolve, reject) => {
proc.on("close", (code, signal) => {
const duration = process.hrtime(start);
printOutput(duration, code, signal);
if (destructors) {
destructors.delete(killProc);
}
resolve({ stdout, stderr, code, signal, duration });
});
proc.on("error", (err) => {
const duration = process.hrtime(start);
printOutput(duration, null, null);
log(`Error: ${err}`);
if (destructors) {
destructors.delete(killProc);
}
reject(err);
});
});
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions