Skip to content

Commit 89a7c85

Browse files
committed
Fix a number of other process.on('exit') bugs similar to #4711
1 parent f29305d commit 89a7c85

File tree

7 files changed

+12
-24
lines changed

7 files changed

+12
-24
lines changed

apps/heft/src/plugins/NodeServicePlugin.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,8 @@ export default class NodeServicePlugin implements IHeftTaskPlugin {
344344

345345
childProcess.on('exit', (code: number | null, signal: string | null) => {
346346
try {
347+
// Under normal conditions we don't reject the promise here, because 'data' events can continue
348+
// to fire as data is flushed, before finally concluding with the 'close' event.
347349
this._logger.terminal.writeVerboseLine(
348350
`The service process fired its "exit" event` + this._formatCodeOrSignal(code, signal)
349351
);

apps/rundown/src/Rundown.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ export class Rundown {
132132
});
133133

134134
await new Promise<void>((resolve, reject) => {
135-
childProcess.on('exit', (code: number | null, signal: string | null): void => {
135+
childProcess.on('close', (code: number | null, signal: string | null): void => {
136136
if (code !== 0 && !ignoreExitCode) {
137137
reject(new Error('Child process terminated with exit code ' + code));
138138
} else if (!completedNormally) {

apps/rundown/src/launcher.ts

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,6 @@ class Launcher {
5050
}
5151
}
5252

53-
/**
54-
* Synchronously delay for the specified time interval.
55-
*/
56-
private static _delayMs(milliseconds: number): void {
57-
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, milliseconds);
58-
}
59-
6053
public installHook(): void {
6154
const realRequire: NodeJS.Require = moduleApi.Module.prototype.require;
6255

@@ -113,17 +106,11 @@ class Launcher {
113106
moduleApi.Module.prototype.require = hookedRequire as NodeJS.Require;
114107
Launcher._copyProperties(hookedRequire, realRequire);
115108

116-
process.on('exit', () => {
109+
process.on('close', () => {
117110
this._sendIpcTraceBatch();
118111
process.send!({
119112
id: 'done'
120113
} as IIpcDone);
121-
122-
// The Node.js "exit" event is synchronous, and the process will terminate as soon as this function returns.
123-
// To avoid a race condition, allow some time for IPC messages to be transmitted to the parent process.
124-
// TODO: There should be a way to eliminate this delay by intercepting earlier in the shutdown sequence,
125-
// but it needs to consider every way that Node.js can exit.
126-
Launcher._delayMs(500);
127114
});
128115
}
129116
}

heft-plugins/heft-storybook-plugin/src/StorybookPlugin.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,7 @@ export default class StorybookPlugin implements IHeftTaskPlugin<IStorybookPlugin
461461
reject(new Error(`Storybook returned error: ${error}`));
462462
});
463463

464-
forkedProcess.on('exit', (code: number | null) => {
464+
forkedProcess.on('close', (code: number | null) => {
465465
if (processFinished) {
466466
return;
467467
}

libraries/node-core-library/src/Executable.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,7 @@ export class Executable {
567567
}
568568
}
569569

570-
let errorThrown: boolean = false;
570+
let errorThrown: Error | undefined = undefined;
571571
const exitCode: number | null = await new Promise<number | null>(
572572
(resolve: (result: number | null) => void, reject: (error: Error) => void) => {
573573
if (encoding) {
@@ -579,13 +579,12 @@ export class Executable {
579579
});
580580
}
581581
childProcess.on('error', (error: Error) => {
582-
errorThrown = true;
583-
reject(error);
582+
// Wait to call reject() until any output is collected
583+
errorThrown = error;
584584
});
585-
childProcess.on('exit', (code: number | null) => {
585+
childProcess.on('close', (code: number | null) => {
586586
if (errorThrown) {
587-
// We've already rejected the promise
588-
return;
587+
reject(errorThrown);
589588
}
590589
if (code !== 0 && throwOnNonZeroExitCode) {
591590
reject(new Error(`Process exited with code ${code}`));

libraries/package-deps-hash/src/getRepoState.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ async function spawnGitAsync(
292292

293293
const [status] = await once(proc, 'close');
294294
if (status !== 0) {
295-
throw new Error(`git ${args[0]} exited with code ${status}: ${stderr}`);
295+
throw new Error(`git ${args[0]} exited with code ${status}:\n${stderr}`);
296296
}
297297

298298
return stdout;

repo-scripts/repo-toolbox/src/BumpCyclicsAction.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ export class BumpCyclicsAction extends CommandLineAction {
8484
const childProcess: ChildProcess = Executable.spawn('npm', ['view', packageName, 'version']);
8585
const stdoutBuffer: string[] = [];
8686
childProcess.stdout!.on('data', (chunk) => stdoutBuffer.push(chunk));
87-
childProcess.on('exit', (code: number) => {
87+
childProcess.on('close', (code: number) => {
8888
if (code) {
8989
reject(new Error(`Exited with ${code}`));
9090
} else {

0 commit comments

Comments
 (0)