Visitar URL original
fix: crash when calling utilityProcess.postMessage() after the proces… · electron/electron@d05abea · GitHub
Skip to content

Commit d05abea

Browse files
fix: crash when calling utilityProcess.postMessage() after the process has exited (#53300)
postMessage() only checked whether the NodeService remote was connected before writing to the message pipe connector, but the connector is torn down separately (from the 'exit' path and from its own error handler), so calling child.postMessage() from an 'exit' listener or during shutdown dereferenced a null connector. Guard on the connector itself. Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com> Co-authored-by: Sam Attard <sattard@anthropic.com>
1 parent 9d3f4ff commit d05abea

3 files changed

Lines changed: 28 additions & 2 deletions

File tree

‎shell/browser/api/electron_api_utility_process.cc‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ void UtilityProcessWrapper::Shutdown(uint32_t exit_code) {
348348
}
349349

350350
void UtilityProcessWrapper::PostMessage(gin::Arguments* const args) {
351-
if (!node_service_remote_.is_connected())
351+
if (!connector_ || connector_closed_)
352352
return;
353353

354354
blink::TransferableMessage transferable_message;
@@ -445,7 +445,7 @@ void UtilityProcessWrapper::OnV8FatalError(const std::string& location,
445445
}
446446

447447
void UtilityProcessWrapper::CreateAndSendURLLoaderFactory(bool /* crashed */) {
448-
if (!node_service_remote_.is_connected())
448+
if (!node_service_remote_.is_bound() || !node_service_remote_.is_connected())
449449
return;
450450

451451
node_service_remote_->UpdateURLLoaderFactory(CreateURLLoaderFactoryParams());
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Calling postMessage() on a utility process from its 'exit' listener, or
2+
// after the process has gone away, must be a no-op rather than crashing the
3+
// main process.
4+
const { app, utilityProcess } = require('electron');
5+
6+
const path = require('node:path');
7+
8+
app.whenReady().then(() => {
9+
const child = utilityProcess.fork(path.join(__dirname, 'utility.js'));
10+
child.on('exit', () => {
11+
child.postMessage('after-exit');
12+
setTimeout(() => {
13+
child.postMessage('after-exit-later');
14+
app.quit();
15+
});
16+
});
17+
child.once('message', () => {
18+
// Child is up; quit while it is still running so the exit event is
19+
// delivered from the shutdown path.
20+
child.postMessage('before-exit');
21+
app.quit();
22+
});
23+
});
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
process.parentPort.on('message', () => {});
2+
process.parentPort.postMessage('ready');
3+
setInterval(() => {}, 1000);

0 commit comments

Comments
 (0)