feat: add error event for utility process (33-x-y) (#43997)

* feat: add error event for utility process (#43774)

* feat: add error event for utility process

* chore: use public report api

* chore: fix lint

* doc: mark error event as experimental

---------

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>

* fixup! feat: add error event for utility process (#43774)

remove #include "electron/mas.h"

this header did not exist before c1c8fbfd9

---------

Co-authored-by: Robo <hop2deep@gmail.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
This commit is contained in:
Charles Kerr 2024-09-29 17:12:15 -05:00 committed by GitHub
parent d8cd86c4fa
commit 5836ea1a78
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 166 additions and 5 deletions

View file

@ -223,7 +223,8 @@ UtilityProcessWrapper::UtilityProcessWrapper(
params->use_network_observer_from_url_loader_factory =
create_network_observer;
node_service_remote_->Initialize(std::move(params));
node_service_remote_->Initialize(std::move(params),
receiver_.BindNewPipeAndPassRemote());
}
UtilityProcessWrapper::~UtilityProcessWrapper() {
@ -258,8 +259,9 @@ void UtilityProcessWrapper::HandleTermination(uint64_t exit_code) {
void UtilityProcessWrapper::OnServiceProcessDisconnected(
uint32_t exit_code,
const std::string& description) {
if (description == "process_exit_termination")
if (description == "process_exit_termination") {
HandleTermination(exit_code);
}
}
void UtilityProcessWrapper::OnServiceProcessTerminatedNormally(
@ -372,6 +374,11 @@ bool UtilityProcessWrapper::Accept(mojo::Message* mojo_message) {
return true;
}
void UtilityProcessWrapper::OnV8FatalError(const std::string& location,
const std::string& report) {
EmitWithoutEvent("error", "FatalError", location, report);
}
// static
raw_ptr<UtilityProcessWrapper> UtilityProcessWrapper::FromProcessId(
base::ProcessId pid) {

View file

@ -44,6 +44,7 @@ class UtilityProcessWrapper final
public gin_helper::Pinnable<UtilityProcessWrapper>,
public gin_helper::EventEmitterMixin<UtilityProcessWrapper>,
public mojo::MessageReceiver,
public node::mojom::NodeServiceClient,
public content::ServiceProcessHost::Observer {
public:
enum class IOHandle : size_t { STDIN = 0, STDOUT = 1, STDERR = 2 };
@ -81,6 +82,10 @@ class UtilityProcessWrapper final
// mojo::MessageReceiver
bool Accept(mojo::Message* mojo_message) override;
// node::mojom::NodeServiceClient
void OnV8FatalError(const std::string& location,
const std::string& report) override;
// content::ServiceProcessHost::Observer
void OnServiceProcessTerminatedNormally(
const content::ServiceProcessInfo& info) override;
@ -102,6 +107,7 @@ class UtilityProcessWrapper final
bool connector_closed_ = false;
std::unique_ptr<mojo::Connector> connector_;
blink::MessagePortDescriptor host_port_;
mojo::Receiver<node::mojom::NodeServiceClient> receiver_{this};
mojo::Remote<node::mojom::NodeService> node_service_remote_;
std::optional<electron::URLLoaderNetworkObserver>
url_loader_network_observer_;

View file

@ -27,6 +27,7 @@
#include "node_options-inl.h"
#include "node_options.h"
#include "node_platform.h"
#include "node_report.h"
#include "tracing/agent.h"
#include "electron/pop_node_defines.h"

View file

@ -4,6 +4,7 @@
#include "shell/services/node/node_service.h"
#include <sstream>
#include <utility>
#include "base/command_line.h"
@ -20,8 +21,32 @@
#include "shell/common/node_includes.h"
#include "shell/services/node/parent_port.h"
#if !IS_MAS_BUILD()
#include "shell/common/crash_keys.h"
#endif
namespace electron {
mojo::Remote<node::mojom::NodeServiceClient> g_client_remote;
void V8FatalErrorCallback(const char* location, const char* message) {
if (g_client_remote.is_bound() && g_client_remote.is_connected()) {
auto* isolate = v8::Isolate::TryGetCurrent();
std::ostringstream outstream;
node::GetNodeReport(isolate, message, location,
v8::Local<v8::Object>() /* error */, outstream);
g_client_remote->OnV8FatalError(location, outstream.str());
}
#if !IS_MAS_BUILD()
electron::crash_keys::SetCrashKey("electron.v8-fatal.message", message);
electron::crash_keys::SetCrashKey("electron.v8-fatal.location", location);
#endif
volatile int* zero = nullptr;
*zero = 0;
}
URLLoaderBundle::URLLoaderBundle() = default;
URLLoaderBundle::~URLLoaderBundle() = default;
@ -73,12 +98,20 @@ NodeService::~NodeService() {
js_env_->DestroyMicrotasksRunner();
node::Stop(node_env_.get(), node::StopFlags::kDoNotTerminateIsolate);
}
if (g_client_remote.is_bound()) {
g_client_remote.reset();
}
}
void NodeService::Initialize(node::mojom::NodeServiceParamsPtr params) {
void NodeService::Initialize(
node::mojom::NodeServiceParamsPtr params,
mojo::PendingRemote<node::mojom::NodeServiceClient> client_pending_remote) {
if (NodeBindings::IsInitialized())
return;
g_client_remote.Bind(std::move(client_pending_remote));
g_client_remote.reset_on_disconnect();
ParentPort::GetInstance()->Initialize(std::move(params->port));
URLLoaderBundle::GetInstance()->SetURLLoaderFactory(
@ -105,6 +138,9 @@ void NodeService::Initialize(node::mojom::NodeServiceParamsPtr params) {
js_env_->isolate()->GetCurrentContext(), js_env_->platform(),
params->args, params->exec_args);
// Override the default handler set by NodeBindings.
node_env_->isolate()->SetFatalErrorHandler(V8FatalErrorCallback);
node::SetProcessExitHandler(
node_env_.get(), [this](node::Environment* env, int exit_code) {
// Destroy node platform.

View file

@ -61,7 +61,9 @@ class NodeService : public node::mojom::NodeService {
NodeService& operator=(const NodeService&) = delete;
// mojom::NodeService implementation:
void Initialize(node::mojom::NodeServiceParamsPtr params) override;
void Initialize(node::mojom::NodeServiceParamsPtr params,
mojo::PendingRemote<node::mojom::NodeServiceClient>
client_pending_remote) override;
private:
// This needs to be initialized first so that it can be destroyed last

View file

@ -20,7 +20,12 @@ struct NodeServiceParams {
bool use_network_observer_from_url_loader_factory = false;
};
interface NodeServiceClient {
OnV8FatalError(string location, string report);
};
[ServiceSandbox=sandbox.mojom.Sandbox.kNoSandbox]
interface NodeService {
Initialize(NodeServiceParams params);
Initialize(NodeServiceParams params,
pending_remote<NodeServiceClient> client_remote);
};