Repository: electron/electron
Pull request: fix: add back fallback wasm-trap handling

Backport of #47186.

See that PR for details.

Notes: none

Changed files:
filename: patches/chromium/.patches
patch: @@ -80,7 +80,6 @@ introduce_ozoneplatform_electron_can_call_x11_property.patch
 make_gtk_getlibgtk_public.patch
 custom_protocols_plzserviceworker.patch
 feat_filter_out_non-shareable_windows_in_the_current_application_in.patch
-disable_freezing_flags_after_init_in_node.patch
 short-circuit_permissions_checks_in_mediastreamdevicescontroller.patch
 chore_add_electron_deps_to_gitignores.patch
 chore_modify_chromium_handling_of_mouse_events.patch

filename: patches/chromium/disable_freezing_flags_after_init_in_node.patch
patch: @@ -1,30 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Jeremy Rose <japthorp@slack-corp.com>
-Date: Mon, 20 Jun 2022 14:53:37 -0700
-Subject: disable freezing flags after init in node
-
-This was introduced in
-https://chromium-review.googlesource.com/c/chromium/src/+/3687671.
-
-When running node in the renderer, flags are updated after initialization, so
-freezing the flags in Blink causes node initialization to fail.
-
-If possible, it would be ideal to do this without a patch.
-https://bugs.chromium.org/p/v8/issues/detail?id=12887 suggests that there may
-at some point be an API to "unfreeze" the flags, or we may be able to refactor
-node initialization to not update flags after V8 initialization.
-
-diff --git a/content/renderer/render_process_impl.cc b/content/renderer/render_process_impl.cc
-index eb11068e932b7b94cbf215d6f84ae427ce77fcd5..9744e45974af215bfbe9e5feb2db7274f8efebf0 100644
---- a/content/renderer/render_process_impl.cc
-+++ b/content/renderer/render_process_impl.cc
-@@ -208,6 +208,9 @@ RenderProcessImpl::RenderProcessImpl()
-     v8::V8::SetFlagsFromString(kSABPerContextFlag, sizeof(kSABPerContextFlag));
-   }
- 
-+  // Freezing flags after init conflicts with node in the renderer.
-+  v8::V8::SetFlagsFromString("--no-freeze-flags-after-init");
-+
-   if (base::FeatureList::IsEnabled(features::kWebAssemblyTrapHandler)) {
-     content::GetContentClient()->renderer()->SetUpWebAssemblyTrapHandler();
-   }

filename: shell/renderer/electron_renderer_client.cc
patch: @@ -6,6 +6,7 @@
 
 #include <algorithm>
 
+#include "base/base_switches.h"
 #include "base/command_line.h"
 #include "base/containers/contains.h"
 #include "base/debug/stack_trace.h"
@@ -25,6 +26,13 @@
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"  // nogncheck
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"  // nogncheck
 
+#if BUILDFLAG(IS_LINUX) && (defined(ARCH_CPU_X86_64) || defined(ARCH_CPU_ARM64))
+#define ENABLE_WEB_ASSEMBLY_TRAP_HANDLER_LINUX
+#include "components/crash/core/app/crashpad.h"
+#include "content/public/common/content_switches.h"
+#include "v8/include/v8-wasm-trap-handler-posix.h"
+#endif
+
 namespace electron {
 
 ElectronRendererClient::ElectronRendererClient()
@@ -35,6 +43,14 @@ ElectronRendererClient::ElectronRendererClient()
 
 ElectronRendererClient::~ElectronRendererClient() = default;
 
+void ElectronRendererClient::PostIOThreadCreated(
+    base::SingleThreadTaskRunner* io_thread_task_runner) {
+  // Freezing flags after init conflicts with node in the renderer.
+  // We do this here in order to avoid having to patch the ctor in
+  // content/renderer/render_process_impl.cc.
+  v8::V8::SetFlagsFromString("--no-freeze-flags-after-init");
+}
+
 void ElectronRendererClient::RenderFrameCreated(
     content::RenderFrame* render_frame) {
   new ElectronRenderFrameObserver(render_frame, this);
@@ -236,6 +252,48 @@ void ElectronRendererClient::WillDestroyWorkerContextOnWorkerThread(
   }
 }
 
+void ElectronRendererClient::SetUpWebAssemblyTrapHandler() {
+// See CL:5372409 - copied from ShellContentRendererClient.
+#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
+  // Mac and Windows use the default implementation (where the default v8 trap
+  // handler gets set up).
+  ContentRendererClient::SetUpWebAssemblyTrapHandler();
+  return;
+#elif defined(ENABLE_WEB_ASSEMBLY_TRAP_HANDLER_LINUX)
+  const bool crash_reporter_enabled =
+      crash_reporter::GetHandlerSocket(nullptr, nullptr);
+
+  if (crash_reporter_enabled) {
+    // If either --enable-crash-reporter or --enable-crash-reporter-for-testing
+    // is enabled it should take care of signal handling for us, use the default
+    // implementation which doesn't register an additional handler.
+    ContentRendererClient::SetUpWebAssemblyTrapHandler();
+    return;
+  }
+
+  const bool use_v8_default_handler =
+      base::CommandLine::ForCurrentProcess()->HasSwitch(
+          ::switches::kDisableInProcessStackTraces);
+
+  if (use_v8_default_handler) {
+    // There is no signal handler yet, but it's okay if v8 registers one.
+    v8::V8::EnableWebAssemblyTrapHandler(/*use_v8_signal_handler=*/true);
+    return;
+  }
+
+  if (base::debug::SetStackDumpFirstChanceCallback(
+          v8::TryHandleWebAssemblyTrapPosix)) {
+    // Crashpad and Breakpad are disabled, but the in-process stack dump
+    // handlers are enabled, so set the callback on the stack dump handlers.
+    v8::V8::EnableWebAssemblyTrapHandler(/*use_v8_signal_handler=*/false);
+    return;
+  }
+
+  // As the registration of the callback failed, we don't enable trap
+  // handlers.
+#endif  // defined(ENABLE_WEB_ASSEMBLY_TRAP_HANDLER_LINUX)
+}
+
 node::Environment* ElectronRendererClient::GetEnvironment(
     content::RenderFrame* render_frame) const {
   if (!injected_frames_.contains(render_frame))

filename: shell/renderer/electron_renderer_client.h
patch: @@ -38,13 +38,16 @@ class ElectronRendererClient : public RendererClientBase {
   void UndeferLoad(content::RenderFrame* render_frame);
 
   // content::ContentRendererClient:
+  void PostIOThreadCreated(
+      base::SingleThreadTaskRunner* io_thread_task_runner) override;
   void RenderFrameCreated(content::RenderFrame*) override;
   void RunScriptsAtDocumentStart(content::RenderFrame* render_frame) override;
   void RunScriptsAtDocumentEnd(content::RenderFrame* render_frame) override;
   void WorkerScriptReadyForEvaluationOnWorkerThread(
       v8::Local<v8::Context> context) override;
   void WillDestroyWorkerContextOnWorkerThread(
       v8::Local<v8::Context> context) override;
+  void SetUpWebAssemblyTrapHandler() override;
 
   node::Environment* GetEnvironment(content::RenderFrame* frame) const;