fix(core): Improve errors in situations where the command spawn does … (#5723)
This commit is contained in:
parent
626844b539
commit
4782113ceb
|
@ -185,6 +185,16 @@ describe('ShellExecutionService', () => {
|
||||||
expect(result.error).toBe(spawnError);
|
expect(result.error).toBe(spawnError);
|
||||||
expect(result.exitCode).toBe(1);
|
expect(result.exitCode).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('handles errors that do not fire the exit event', async () => {
|
||||||
|
const error = new Error('spawn abc ENOENT');
|
||||||
|
const { result } = await simulateExecution('touch cat.jpg', (cp) => {
|
||||||
|
cp.emit('error', error); // No exit event is fired.
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result.error).toBe(error);
|
||||||
|
expect(result.exitCode).toBe(1);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Aborting Commands', () => {
|
describe('Aborting Commands', () => {
|
||||||
|
|
|
@ -174,7 +174,19 @@ export class ShellExecutionService {
|
||||||
child.stdout.on('data', (data) => handleOutput(data, 'stdout'));
|
child.stdout.on('data', (data) => handleOutput(data, 'stdout'));
|
||||||
child.stderr.on('data', (data) => handleOutput(data, 'stderr'));
|
child.stderr.on('data', (data) => handleOutput(data, 'stderr'));
|
||||||
child.on('error', (err) => {
|
child.on('error', (err) => {
|
||||||
|
const { stdout, stderr, finalBuffer } = cleanup();
|
||||||
error = err;
|
error = err;
|
||||||
|
resolve({
|
||||||
|
error,
|
||||||
|
stdout,
|
||||||
|
stderr,
|
||||||
|
rawOutput: finalBuffer,
|
||||||
|
output: stdout + (stderr ? `\n${stderr}` : ''),
|
||||||
|
exitCode: 1,
|
||||||
|
signal: null,
|
||||||
|
aborted: false,
|
||||||
|
pid: child.pid,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const abortHandler = async () => {
|
const abortHandler = async () => {
|
||||||
|
@ -200,18 +212,8 @@ export class ShellExecutionService {
|
||||||
|
|
||||||
abortSignal.addEventListener('abort', abortHandler, { once: true });
|
abortSignal.addEventListener('abort', abortHandler, { once: true });
|
||||||
|
|
||||||
child.on('exit', (code, signal) => {
|
child.on('exit', (code: number, signal: NodeJS.Signals) => {
|
||||||
exited = true;
|
const { stdout, stderr, finalBuffer } = cleanup();
|
||||||
abortSignal.removeEventListener('abort', abortHandler);
|
|
||||||
|
|
||||||
if (stdoutDecoder) {
|
|
||||||
stdout += stripAnsi(stdoutDecoder.decode());
|
|
||||||
}
|
|
||||||
if (stderrDecoder) {
|
|
||||||
stderr += stripAnsi(stderrDecoder.decode());
|
|
||||||
}
|
|
||||||
|
|
||||||
const finalBuffer = Buffer.concat(outputChunks);
|
|
||||||
|
|
||||||
resolve({
|
resolve({
|
||||||
rawOutput: finalBuffer,
|
rawOutput: finalBuffer,
|
||||||
|
@ -225,6 +227,25 @@ export class ShellExecutionService {
|
||||||
pid: child.pid,
|
pid: child.pid,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cleans up a process (and it's accompanying state) that is exiting or
|
||||||
|
* erroring and returns output formatted output buffers and strings
|
||||||
|
*/
|
||||||
|
function cleanup() {
|
||||||
|
exited = true;
|
||||||
|
abortSignal.removeEventListener('abort', abortHandler);
|
||||||
|
if (stdoutDecoder) {
|
||||||
|
stdout += stripAnsi(stdoutDecoder.decode());
|
||||||
|
}
|
||||||
|
if (stderrDecoder) {
|
||||||
|
stderr += stripAnsi(stderrDecoder.decode());
|
||||||
|
}
|
||||||
|
|
||||||
|
const finalBuffer = Buffer.concat(outputChunks);
|
||||||
|
|
||||||
|
return { stdout, stderr, finalBuffer };
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return { pid: child.pid, result };
|
return { pid: child.pid, result };
|
||||||
|
|
Loading…
Reference in New Issue