fix: ensure utilityProcess
only emits one 'exit' event (#44268)
fix: ensure utilityProcess only emits one exit Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com> Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
This commit is contained in:
parent
db2050e9d2
commit
b39ba84e87
3 changed files with 21 additions and 11 deletions
|
@ -246,12 +246,16 @@ void UtilityProcessWrapper::OnServiceProcessLaunch(
|
||||||
}
|
}
|
||||||
|
|
||||||
void UtilityProcessWrapper::HandleTermination(uint64_t exit_code) {
|
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)
|
if (pid_ != base::kNullProcessId)
|
||||||
GetAllUtilityProcessWrappers().Remove(pid_);
|
GetAllUtilityProcessWrappers().Remove(pid_);
|
||||||
CloseConnectorPort();
|
CloseConnectorPort();
|
||||||
|
|
||||||
EmitWithoutEvent("exit", exit_code);
|
EmitWithoutEvent("exit", exit_code);
|
||||||
|
|
||||||
Unpin();
|
Unpin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,13 +294,8 @@ void UtilityProcessWrapper::CloseConnectorPort() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void UtilityProcessWrapper::Shutdown(uint64_t exit_code) {
|
void UtilityProcessWrapper::Shutdown(uint64_t exit_code) {
|
||||||
if (pid_ != base::kNullProcessId)
|
|
||||||
GetAllUtilityProcessWrappers().Remove(pid_);
|
|
||||||
node_service_remote_.reset();
|
node_service_remote_.reset();
|
||||||
CloseConnectorPort();
|
HandleTermination(exit_code);
|
||||||
// Emit 'exit' event
|
|
||||||
EmitWithoutEvent("exit", exit_code);
|
|
||||||
Unpin();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UtilityProcessWrapper::PostMessage(gin::Arguments* args) {
|
void UtilityProcessWrapper::PostMessage(gin::Arguments* args) {
|
||||||
|
|
|
@ -98,6 +98,7 @@ class UtilityProcessWrapper final
|
||||||
int stdout_read_fd_ = -1;
|
int stdout_read_fd_ = -1;
|
||||||
int stderr_read_fd_ = -1;
|
int stderr_read_fd_ = -1;
|
||||||
bool connector_closed_ = false;
|
bool connector_closed_ = false;
|
||||||
|
bool terminated_ = false;
|
||||||
std::unique_ptr<mojo::Connector> connector_;
|
std::unique_ptr<mojo::Connector> connector_;
|
||||||
blink::MessagePortDescriptor host_port_;
|
blink::MessagePortDescriptor host_port_;
|
||||||
mojo::Remote<node::mojom::NodeService> node_service_remote_;
|
mojo::Remote<node::mojom::NodeService> node_service_remote_;
|
||||||
|
|
|
@ -58,10 +58,20 @@ describe('utilityProcess module', () => {
|
||||||
await once(child, 'spawn');
|
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 child = utilityProcess.fork(path.join(fixturesPath, 'empty.js'));
|
||||||
const [code] = await once(child, 'exit');
|
child.on('exit', (code) => {
|
||||||
expect(code).to.equal(0);
|
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 () => {
|
ifit(!isWindows32Bit)('emits the correct error code when child process exits nonzero', async () => {
|
||||||
|
|
Loading…
Reference in a new issue