From e1419b2fdf78eb0bfb13be1cf88f59530e96f7b7 Mon Sep 17 00:00:00 2001 From: "trop[bot]" <37223003+trop[bot]@users.noreply.github.com> Date: Wed, 16 Oct 2024 15:01:09 -0400 Subject: [PATCH] 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 --- .../browser/api/electron_api_utility_process.cc | 15 +++++++-------- shell/browser/api/electron_api_utility_process.h | 1 + spec/api-utility-process-spec.ts | 16 +++++++++++++--- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/shell/browser/api/electron_api_utility_process.cc b/shell/browser/api/electron_api_utility_process.cc index 35bb3972958f..29e5f719d923 100644 --- a/shell/browser/api/electron_api_utility_process.cc +++ b/shell/browser/api/electron_api_utility_process.cc @@ -247,12 +247,16 @@ void UtilityProcessWrapper::OnServiceProcessLaunch( } void UtilityProcessWrapper::HandleTermination(uint64_t exit_code) { + // HandleTermination is called from multiple callsites, + // we need to ensure we only process it for the first callsite. + if (terminated_) + return; + terminated_ = true; + if (pid_ != base::kNullProcessId) GetAllUtilityProcessWrappers().Remove(pid_); CloseConnectorPort(); - EmitWithoutEvent("exit", exit_code); - Unpin(); } @@ -292,13 +296,8 @@ void UtilityProcessWrapper::CloseConnectorPort() { } void UtilityProcessWrapper::Shutdown(uint64_t exit_code) { - if (pid_ != base::kNullProcessId) - GetAllUtilityProcessWrappers().Remove(pid_); node_service_remote_.reset(); - CloseConnectorPort(); - // Emit 'exit' event - EmitWithoutEvent("exit", exit_code); - Unpin(); + HandleTermination(exit_code); } void UtilityProcessWrapper::PostMessage(gin::Arguments* args) { diff --git a/shell/browser/api/electron_api_utility_process.h b/shell/browser/api/electron_api_utility_process.h index c0a992ba7fe4..7d5eae1710c8 100644 --- a/shell/browser/api/electron_api_utility_process.h +++ b/shell/browser/api/electron_api_utility_process.h @@ -105,6 +105,7 @@ class UtilityProcessWrapper final int stdout_read_fd_ = -1; int stderr_read_fd_ = -1; bool connector_closed_ = false; + bool terminated_ = false; std::unique_ptr connector_; blink::MessagePortDescriptor host_port_; mojo::Receiver receiver_{this}; diff --git a/spec/api-utility-process-spec.ts b/spec/api-utility-process-spec.ts index 2a12a45790fa..e27eae06f884 100644 --- a/spec/api-utility-process-spec.ts +++ b/spec/api-utility-process-spec.ts @@ -58,10 +58,20 @@ describe('utilityProcess module', () => { await once(child, 'spawn'); }); - it('emits \'exit\' when child process exits gracefully', async () => { + it('emits \'exit\' when child process exits gracefully', (done) => { const child = utilityProcess.fork(path.join(fixturesPath, 'empty.js')); - const [code] = await once(child, 'exit'); - expect(code).to.equal(0); + child.on('exit', (code) => { + expect(code).to.equal(0); + done(); + }); + }); + + it('emits \'exit\' when the child process file does not exist', (done) => { + const child = utilityProcess.fork('nonexistent'); + child.on('exit', (code) => { + expect(code).to.equal(1); + done(); + }); }); ifit(!isWindows32Bit)('emits the correct error code when child process exits nonzero', async () => {