summaryrefslogtreecommitdiff
path: root/packages/core/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/core/src')
-rw-r--r--packages/core/src/services/shellExecutionService.test.ts10
-rw-r--r--packages/core/src/services/shellExecutionService.ts45
2 files changed, 43 insertions, 12 deletions
diff --git a/packages/core/src/services/shellExecutionService.test.ts b/packages/core/src/services/shellExecutionService.test.ts
index cfce08d2..2fe51a5e 100644
--- a/packages/core/src/services/shellExecutionService.test.ts
+++ b/packages/core/src/services/shellExecutionService.test.ts
@@ -185,6 +185,16 @@ describe('ShellExecutionService', () => {
expect(result.error).toBe(spawnError);
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', () => {
diff --git a/packages/core/src/services/shellExecutionService.ts b/packages/core/src/services/shellExecutionService.ts
index d1126a7d..3749fcf6 100644
--- a/packages/core/src/services/shellExecutionService.ts
+++ b/packages/core/src/services/shellExecutionService.ts
@@ -174,7 +174,19 @@ export class ShellExecutionService {
child.stdout.on('data', (data) => handleOutput(data, 'stdout'));
child.stderr.on('data', (data) => handleOutput(data, 'stderr'));
child.on('error', (err) => {
+ const { stdout, stderr, finalBuffer } = cleanup();
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 () => {
@@ -200,18 +212,8 @@ export class ShellExecutionService {
abortSignal.addEventListener('abort', abortHandler, { once: true });
- child.on('exit', (code, signal) => {
- exited = true;
- abortSignal.removeEventListener('abort', abortHandler);
-
- if (stdoutDecoder) {
- stdout += stripAnsi(stdoutDecoder.decode());
- }
- if (stderrDecoder) {
- stderr += stripAnsi(stderrDecoder.decode());
- }
-
- const finalBuffer = Buffer.concat(outputChunks);
+ child.on('exit', (code: number, signal: NodeJS.Signals) => {
+ const { stdout, stderr, finalBuffer } = cleanup();
resolve({
rawOutput: finalBuffer,
@@ -225,6 +227,25 @@ export class ShellExecutionService {
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 };