Skip to content

Commit e1419b2

Browse files
fix: ensure utilityProcess only emits one 'exit' event (#44266)
fix: ensure utilityProcess only emits one exit Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com> Co-authored-by: Shelley Vohr <[email protected]>
1 parent 11c2b61 commit e1419b2

File tree

3 files changed

+21
-11
lines changed

3 files changed

+21
-11
lines changed

shell/browser/api/electron_api_utility_process.cc

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -247,12 +247,16 @@ void UtilityProcessWrapper::OnServiceProcessLaunch(
247247
}
248248

249249
void UtilityProcessWrapper::HandleTermination(uint64_t exit_code) {
250+
// HandleTermination is called from multiple callsites,
251+
// we need to ensure we only process it for the first callsite.
252+
if (terminated_)
253+
return;
254+
terminated_ = true;
255+
250256
if (pid_ != base::kNullProcessId)
251257
GetAllUtilityProcessWrappers().Remove(pid_);
252258
CloseConnectorPort();
253-
254259
EmitWithoutEvent("exit", exit_code);
255-
256260
Unpin();
257261
}
258262

@@ -292,13 +296,8 @@ void UtilityProcessWrapper::CloseConnectorPort() {
292296
}
293297

294298
void UtilityProcessWrapper::Shutdown(uint64_t exit_code) {
295-
if (pid_ != base::kNullProcessId)
296-
GetAllUtilityProcessWrappers().Remove(pid_);
297299
node_service_remote_.reset();
298-
CloseConnectorPort();
299-
// Emit 'exit' event
300-
EmitWithoutEvent("exit", exit_code);
301-
Unpin();
300+
HandleTermination(exit_code);
302301
}
303302

304303
void UtilityProcessWrapper::PostMessage(gin::Arguments* args) {

shell/browser/api/electron_api_utility_process.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ class UtilityProcessWrapper final
105105
int stdout_read_fd_ = -1;
106106
int stderr_read_fd_ = -1;
107107
bool connector_closed_ = false;
108+
bool terminated_ = false;
108109
std::unique_ptr<mojo::Connector> connector_;
109110
blink::MessagePortDescriptor host_port_;
110111
mojo::Receiver<node::mojom::NodeServiceClient> receiver_{this};

spec/api-utility-process-spec.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,20 @@ describe('utilityProcess module', () => {
5858
await once(child, 'spawn');
5959
});
6060

61-
it('emits \'exit\' when child process exits gracefully', async () => {
61+
it('emits \'exit\' when child process exits gracefully', (done) => {
6262
const child = utilityProcess.fork(path.join(fixturesPath, 'empty.js'));
63-
const [code] = await once(child, 'exit');
64-
expect(code).to.equal(0);
63+
child.on('exit', (code) => {
64+
expect(code).to.equal(0);
65+
done();
66+
});
67+
});
68+
69+
it('emits \'exit\' when the child process file does not exist', (done) => {
70+
const child = utilityProcess.fork('nonexistent');
71+
child.on('exit', (code) => {
72+
expect(code).to.equal(1);
73+
done();
74+
});
6575
});
6676

6777
ifit(!isWindows32Bit)('emits the correct error code when child process exits nonzero', async () => {

0 commit comments

Comments
 (0)