mirror of
https://github.com/electron/electron.git
synced 2026-04-10 03:01:51 -04:00
fix: don't hang on SendSync if ElectronBrowser receiver is destroyed (6-0-x) (#20547)
This commit is contained in:
@@ -82,6 +82,7 @@ class IPCRenderer : public mate::Wrappable<IPCRenderer> {
|
||||
bool internal,
|
||||
const std::string& channel,
|
||||
const base::ListValue& arguments) {
|
||||
std::string error;
|
||||
base::Value result;
|
||||
|
||||
// A task is posted to a separate thread to execute the request so that
|
||||
@@ -98,43 +99,71 @@ class IPCRenderer : public mate::Wrappable<IPCRenderer> {
|
||||
// interface.
|
||||
auto interface_info = electron_browser_ptr_.PassInterface();
|
||||
task_runner->PostTask(
|
||||
FROM_HERE, base::BindOnce(&IPCRenderer::SendMessageSyncOnWorkerThread,
|
||||
base::Unretained(&interface_info),
|
||||
base::Unretained(&response_received_event),
|
||||
base::Unretained(&result), internal, channel,
|
||||
base::Unretained(&arguments)));
|
||||
FROM_HERE,
|
||||
base::BindOnce(&IPCRenderer::SendMessageSyncOnWorkerThread,
|
||||
base::Unretained(this),
|
||||
base::Unretained(&interface_info),
|
||||
base::Unretained(&response_received_event),
|
||||
base::Unretained(&result), internal, channel,
|
||||
base::Unretained(&arguments), base::Unretained(&error)));
|
||||
response_received_event.Wait();
|
||||
electron_browser_ptr_.Bind(std::move(interface_info));
|
||||
if (!error.empty()) {
|
||||
args->ThrowError(error);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
static void SendMessageSyncOnWorkerThread(
|
||||
void SendMessageSyncOnWorkerThread(
|
||||
atom::mojom::ElectronBrowserPtrInfo* interface_info,
|
||||
base::WaitableEvent* event,
|
||||
base::Value* result,
|
||||
bool internal,
|
||||
const std::string& channel,
|
||||
const base::ListValue* arguments) {
|
||||
const base::ListValue* arguments,
|
||||
std::string* error) {
|
||||
atom::mojom::ElectronBrowserPtr browser_ptr(std::move(*interface_info));
|
||||
browser_ptr->MessageSync(
|
||||
electron_browser_ptr_ = std::move(browser_ptr);
|
||||
|
||||
electron_browser_ptr_.set_connection_error_handler(
|
||||
base::BindOnce(&IPCRenderer::HandleMojoConnectionErrorOnWorkerThread,
|
||||
base::Unretained(&electron_browser_ptr_),
|
||||
base::Unretained(interface_info),
|
||||
base::Unretained(event), base::Unretained(error)));
|
||||
electron_browser_ptr_->MessageSync(
|
||||
internal, channel, arguments->Clone(),
|
||||
base::BindOnce(&IPCRenderer::ReturnSyncResponseToMainThread,
|
||||
std::move(browser_ptr), base::Unretained(interface_info),
|
||||
base::Unretained(&electron_browser_ptr_),
|
||||
base::Unretained(interface_info),
|
||||
base::Unretained(event), base::Unretained(result)));
|
||||
}
|
||||
static void ReturnSyncResponseToMainThread(
|
||||
atom::mojom::ElectronBrowserPtr ptr,
|
||||
atom::mojom::ElectronBrowserPtr* ptr,
|
||||
atom::mojom::ElectronBrowserPtrInfo* interface_info,
|
||||
base::WaitableEvent* event,
|
||||
base::Value* result,
|
||||
base::Value response) {
|
||||
*result = std::move(response);
|
||||
*interface_info = ptr.PassInterface();
|
||||
*interface_info = ptr->PassInterface();
|
||||
event->Signal();
|
||||
}
|
||||
// If the other end of the message pipe disconnects, ensure we don't hang the
|
||||
// main thread forever.
|
||||
static void HandleMojoConnectionErrorOnWorkerThread(
|
||||
atom::mojom::ElectronBrowserPtr* ptr,
|
||||
atom::mojom::ElectronBrowserPtrInfo* interface_info,
|
||||
base::WaitableEvent* event,
|
||||
std::string* error) {
|
||||
LOG(INFO) << "Mojo connection interuppted, likely due to the Mojo receiver "
|
||||
"process crashing.";
|
||||
*error = "IPC connection fatally interrupted.";
|
||||
*interface_info = ptr->PassInterface();
|
||||
event->Signal();
|
||||
}
|
||||
|
||||
atom::mojom::ElectronBrowserPtr electron_browser_ptr_;
|
||||
atom::mojom::ElectronBrowserPtr worker_thread_electron_browser_ptr_;
|
||||
};
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
|
||||
Reference in New Issue
Block a user