Backed out changeset 7a28c229e654 (bug 1594998) for causing bustages CLOSED TREE
authorCiure Andrei <aciure@mozilla.com>
Fri, 15 Nov 2019 03:26:34 +0200
changeset 502090 3804c0fce172517dbd396f912eb478aa1418251c
parent 502089 7a28c229e654d10ca9ab630e42753954390e67a7
child 502091 cdd42a28797258b726b8f50f96bd5930ac4e946f
push id114172
push userdluca@mozilla.com
push dateTue, 19 Nov 2019 11:31:10 +0000
treeherdermozilla-inbound@b5c5ba07d3db [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1594998
milestone72.0a1
backs out7a28c229e654d10ca9ab630e42753954390e67a7
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out changeset 7a28c229e654 (bug 1594998) for causing bustages CLOSED TREE
Cargo.lock
js/moz.configure
js/src/build.rs
js/src/make-source-package.sh
js/src/rust/shared/Cargo.toml
js/src/rust/shared/lib.rs
js/src/vm/Initialization.cpp
mozglue/static/README
mozglue/static/rust/Cargo.toml
mozglue/static/rust/build.rs
mozglue/static/rust/lib.rs
mozglue/static/rust/wrappers.cpp
testing/mozbase/mozcrash/mozcrash/mozcrash.py
toolkit/library/rust/shared/Cargo.toml
toolkit/library/rust/shared/lib.rs
toolkit/xre/nsAppRunner.cpp
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1404,16 +1404,17 @@ dependencies = [
  "nsstring-gtest 0.1.0",
  "xpcom-gtest 0.1.0",
 ]
 
 [[package]]
 name = "gkrust-shared"
 version = "0.1.0"
 dependencies = [
+ "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "audio_thread_priority 0.20.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "audioipc-client 0.4.0",
  "audioipc-server 0.2.3",
  "authenticator 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitsdownload 0.1.0",
  "bookmark_sync 0.1.0",
  "cert_storage 0.0.1",
  "cose-c 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1708,17 +1709,16 @@ dependencies = [
 
 [[package]]
 name = "jsrust_shared"
 version = "0.1.0"
 dependencies = [
  "baldrdash 0.1.0",
  "encoding_c 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "encoding_c_mem 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "mozglue-static 0.1.0",
  "mozilla-central-workspace-hack 0.1.0",
 ]
 
 [[package]]
 name = "kernel32-sys"
 version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
@@ -2180,24 +2180,16 @@ version = "0.1.0"
 dependencies = [
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
-name = "mozglue-static"
-version = "0.1.0"
-dependencies = [
- "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
 name = "mozilla-central-workspace-hack"
 version = "0.1.0"
 dependencies = [
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
--- a/js/moz.configure
+++ b/js/moz.configure
@@ -83,22 +83,16 @@ set_define('STATIC_JS_API', static_js_ap
 @depends(shared_js)
 def static_js(value):
     if not value:
         return True
 
 set_define('MOZ_STATIC_JS', static_js)
 
 
-js_option(env='NO_RUST_PANIC_HOOK', when=js_standalone,
-          help='Disable rust panic hook')
-
-set_define('NO_RUST_PANIC_HOOK', True, when='NO_RUST_PANIC_HOOK')
-
-
 # JIT support
 # =======================================================
 @depends(target)
 def ion_default(target):
     if target.cpu in ('x86', 'x86_64', 'arm', 'aarch64', 'mips32', 'mips64'):
         return True
     return False
 
--- a/js/src/build.rs
+++ b/js/src/build.rs
@@ -42,17 +42,16 @@ fn main() {
                // good.
                "--no-jemalloc",
                // Don't try to clobber the output directory. Without
                // this option, the build will fail because the directory
                // already exists but wasn't created by autospider.
                "--dep",
                "--objdir", &out_dir,
                &variant])
-        .env("NO_RUST_PANIC_HOOK", "1")
         .env("SOURCE", &js_src)
         .env("PWD", &js_src)
         .stdout(Stdio::inherit())
         .stderr(Stdio::inherit());
     println!("Running command: {:?}", cmd);
     let result = cmd
         .status()
         .expect("Should spawn autospider OK");
--- a/js/src/make-source-package.sh
+++ b/js/src/make-source-package.sh
@@ -104,17 +104,16 @@ case $cmd in
         ${tgtpath}/modules/
 
     ${MKDIR} -p ${tgtpath}/mozglue
     cp -pPR \
         ${TOPSRCDIR}/mozglue/baseprofiler \
         ${TOPSRCDIR}/mozglue/build \
         ${TOPSRCDIR}/mozglue/misc \
         ${TOPSRCDIR}/mozglue/moz.build \
-        ${TOPSRCDIR}/mozglue/static \
         ${tgtpath}/mozglue/
 
     ${MKDIR} -p ${tgtpath}/tools/fuzzing
     cp -pPR \
         ${TOPSRCDIR}/tools/fuzzing/moz.build \
         ${TOPSRCDIR}/tools/fuzzing/interface \
         ${TOPSRCDIR}/tools/fuzzing/registry \
         ${TOPSRCDIR}/tools/fuzzing/libfuzzer \
--- a/js/src/rust/shared/Cargo.toml
+++ b/js/src/rust/shared/Cargo.toml
@@ -8,17 +8,16 @@ crate-type = ["rlib"]
 name = "jsrust_shared"
 path = "lib.rs"
 
 [dependencies]
 baldrdash = { path = "../../wasm/cranelift", optional = true }
 encoding_c = "0.9.5"
 encoding_c_mem = "0.2.4"
 mozilla-central-workspace-hack = { path = "../../../../build/workspace-hack" }
-mozglue-static = { path = "../../../../mozglue/static/rust" }
 
 [features]
 cranelift_x86 = ['baldrdash/cranelift_x86']
 cranelift_arm32 = ['baldrdash/cranelift_arm32']
 cranelift_arm64 = ['baldrdash/cranelift_arm64']
 cranelift_none = ['baldrdash/cranelift_none']
 simd-accel = ['encoding_c/simd-accel']
 
--- a/js/src/rust/shared/lib.rs
+++ b/js/src/rust/shared/lib.rs
@@ -12,9 +12,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 #[cfg(feature = "baldrdash")]
 extern crate baldrdash;
 
 extern crate encoding_c;
 extern crate encoding_c_mem;
-extern crate mozglue_static;
--- a/js/src/vm/Initialization.cpp
+++ b/js/src/vm/Initialization.cpp
@@ -87,18 +87,16 @@ static void CheckCanonicalNaN() {
 #endif
 }
 
 #define RETURN_IF_FAIL(code)           \
   do {                                 \
     if (!code) return #code " failed"; \
   } while (0)
 
-extern "C" void install_rust_panic_hook();
-
 JS_PUBLIC_API const char* JS::detail::InitWithFailureDiagnostic(
     bool isDebugBuild) {
   // Verify that our DEBUG setting matches the caller's.
 #ifdef DEBUG
   MOZ_RELEASE_ASSERT(isDebugBuild);
 #else
   MOZ_RELEASE_ASSERT(!isDebugBuild);
 #endif
@@ -106,20 +104,16 @@ JS_PUBLIC_API const char* JS::detail::In
   MOZ_ASSERT(libraryInitState == InitState::Uninitialized,
              "must call JS_Init once before any JSAPI operation except "
              "JS_SetICUMemoryFunctions");
   MOZ_ASSERT(!JSRuntime::hasLiveRuntimes(),
              "how do we have live runtimes before JS_Init?");
 
   libraryInitState = InitState::Initializing;
 
-#ifndef NO_RUST_PANIC_HOOK
-  install_rust_panic_hook();
-#endif
-
   PRMJ_NowInit();
 
   js::SliceBudget::Init();
 
   // The first invocation of `ProcessCreation` creates a temporary thread
   // and crashes if that fails, i.e. because we're out of memory. To prevent
   // that from happening at some later time, get it out of the way during
   // startup.
deleted file mode 100644
--- a/mozglue/static/README
+++ /dev/null
@@ -1,2 +0,0 @@
-mozglue/static contains parts of the mozglue library that can/should be
-statically linked to e.g. js/Gecko.
deleted file mode 100644
--- a/mozglue/static/rust/Cargo.toml
+++ /dev/null
@@ -1,14 +0,0 @@
-[package]
-name = "mozglue-static"
-version = "0.1.0"
-edition = "2018"
-license = "MPL"
-
-[lib]
-path = "lib.rs"
-
-[dependencies]
-arrayvec = "0.5"
-
-[build-dependencies]
-cc = "1"
deleted file mode 100644
--- a/mozglue/static/rust/build.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-use std::env;
-use std::path::PathBuf;
-
-fn main() {
-    let dist_path = {
-        let path = PathBuf::from(env::var_os("MOZ_DIST").unwrap());
-        if !path.is_absolute() || !path.is_dir() {
-            panic!("MOZ_DIST must be an absolute directory, was: {}", path.display());
-        }
-        path
-    };
-    let mut build = cc::Build::new();
-    build.cpp(true);
-    build.include(dist_path.join("include"));
-    build.define("MOZ_HAS_MOZGLUE", None);
-    build.file("wrappers.cpp");
-    build.compile("wrappers");
-    println!("cargo:rerun-if-changed=wrappers.cpp");
-}
deleted file mode 100644
--- a/mozglue/static/rust/lib.rs
+++ /dev/null
@@ -1,98 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-use std::os::raw::c_char;
-use std::os::raw::c_int;
-use std::cmp;
-use std::panic;
-use std::ops::Deref;
-use arrayvec::{Array, ArrayString};
-
-#[link(name="wrappers")]
-extern "C" {
-    // We can't use MOZ_Crash directly because it may be weakly linked
-    // and rust can't handle that.
-    fn RustMozCrash(filename: *const c_char, line: c_int, reason: *const c_char) -> !;
-}
-
-/// Truncate a string at the closest unicode character boundary
-/// ```
-/// assert_eq!(str_truncate_valid("éà", 3), "é");
-/// assert_eq!(str_truncate_valid("éà", 4), "éè");
-/// ```
-fn str_truncate_valid(s: &str, mut mid: usize) -> &str {
-    loop {
-        if let Some(res) = s.get(..mid) {
-            return res;
-        }
-        mid -= 1;
-    }
-}
-
-/// Similar to ArrayString, but with terminating nul character.
-#[derive(Debug, PartialEq)]
-struct ArrayCString<A: Array<Item = u8> + Copy> {
-    inner: ArrayString<A>,
-}
-
-impl<S: AsRef<str>, A: Array<Item = u8> + Copy> From<S> for ArrayCString<A> {
-    /// Contrary to ArrayString::from, truncates at the closest unicode
-    /// character boundary.
-    /// ```
-    /// assert_eq!(ArrayCString::<[_; 4]>::from("éà"),
-    ///            ArrayCString::<[_; 4]>::from("é"));
-    /// assert_eq!(&*ArrayCString::<[_; 4]>::from("éà"), "é\0");
-    /// ```
-    fn from(s: S) -> Self {
-        let s = s.as_ref();
-        let len = cmp::min(s.len(), A::CAPACITY - 1);
-        let mut result = Self {
-            inner: ArrayString::from(str_truncate_valid(s, len)).unwrap(),
-        };
-        result.inner.push('\0');
-        result
-    }
-}
-
-impl<A: Array<Item = u8> + Copy> Deref for ArrayCString<A> {
-    type Target = str;
-
-    fn deref(&self) -> &str {
-        self.inner.as_str()
-    }
-}
-
-fn panic_hook(info: &panic::PanicInfo) {
-    // Try to handle &str/String payloads, which should handle 99% of cases.
-    let payload = info.payload();
-    let message = if let Some(s) = payload.downcast_ref::<&str>() {
-        s
-    } else if let Some(s) = payload.downcast_ref::<String>() {
-        s.as_str()
-    } else {
-        // Not the most helpful thing, but seems unlikely to happen
-        // in practice.
-        "Unhandled rust panic payload!"
-    };
-    let (filename, line) = if let Some(loc) = info.location() {
-        (loc.file(), loc.line())
-    } else {
-        ("unknown.rs", 0)
-    };
-    // Copy the message and filename to the stack in order to safely add
-    // a terminating nul character (since rust strings don't come with one
-    // and RustMozCrash wants one).
-    let message = ArrayCString::<[_; 512]>::from(message);
-    let filename = ArrayCString::<[_; 512]>::from(filename);
-    unsafe {
-        RustMozCrash(filename.as_ptr() as *const c_char, line as c_int,
-                 message.as_ptr() as *const c_char);
-    }
-}
-
-/// Configure a panic hook to redirect rust panics to MFBT's MOZ_Crash.
-#[no_mangle]
-pub extern "C" fn install_rust_panic_hook() {
-    panic::set_hook(Box::new(panic_hook));
-}
deleted file mode 100644
--- a/mozglue/static/rust/wrappers.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-// Because this file is compiled from rust, it hits code in
-// config/makefiles/rust.mk that adds -DMOZILLA_CONFIG_H=1 to CFLAGS,
-// which inhibits the -include mozilla-config.h. But we do want
-// mozilla-config.h to be included _and_ to actually do something,
-// so we undefined MOZILLA_CONFIG_H and reinclude mozilla-config.h here.
-// This ensures the right configuration for e.g. MOZ_GLUE_IN_PROGRAM,
-// used in the MFBT headers included further below.
-#undef MOZILLA_CONFIG_H
-#include "mozilla-config.h"
-#include "mozilla/Assertions.h"
-#include "mozilla/Types.h"
-
-// MOZ_Crash wrapper for use by rust, since MOZ_Crash is an inline function.
-extern "C" void RustMozCrash(const char* aFilename, int aLine,
-                             const char* aReason) {
-  MOZ_Crash(aFilename, aLine, aReason);
-}
--- a/testing/mozbase/mozcrash/mozcrash/mozcrash.py
+++ b/testing/mozbase/mozcrash/mozcrash/mozcrash.py
@@ -135,17 +135,17 @@ def log_crashes(logger,
         logger.crash(process=process, test=test, **kwargs)
     return crash_count
 
 
 # Function signatures of abort functions which should be ignored when
 # determining the appropriate frame for the crash signature.
 ABORT_SIGNATURES = (
     "Abort(char const*)",
-    "RustMozCrash",
+    "GeckoCrash",
     "NS_DebugBreak",
     # This signature is part of Rust panic stacks on some platforms. On
     # others, it includes a template parameter containing "core::panic::" and
     # is automatically filtered out by that pattern.
     "core::ops::function::Fn::call",
     "gkrust_shared::panic_hook",
     "intentional_panic",
     "mozalloc_abort",
--- a/toolkit/library/rust/shared/Cargo.toml
+++ b/toolkit/library/rust/shared/Cargo.toml
@@ -29,16 +29,17 @@ authenticator = "0.2.6"
 gkrust_utils = { path = "../../../../xpcom/rust/gkrust_utils" }
 rsdparsa_capi = { path = "../../../../media/webrtc/signaling/src/sdp/rsdparsa_capi" }
 xulstore = { path = "../../../components/xulstore", optional = true }
 # We have these to enforce common feature sets for said crates.
 log = {version = "0.4", features = ["release_max_level_info"]}
 env_logger = {version = "0.6", default-features = false} # disable `regex` to reduce code size
 cose-c = { version = "0.1.5" }
 jsrust_shared = { path = "../../../../js/src/rust/shared" }
+arrayvec = "0.5"
 cert_storage = { path = "../../../../security/manager/ssl/cert_storage", optional = true }
 bitsdownload = { path = "../../../components/bitsdownload", optional = true }
 storage = { path = "../../../../storage/rust" }
 bookmark_sync = { path = "../../../components/places/bookmark_sync", optional = true }
 shift_or_euc_c = "0.1.0"
 audio_thread_priority = "0.20.2"
 mdns_service = { path="../../../../media/mtransport/mdns_service", optional = true }
 neqo_glue = { path = "../../../../netwerk/socket/neqo_glue" }
--- a/toolkit/library/rust/shared/lib.rs
+++ b/toolkit/library/rust/shared/lib.rs
@@ -42,37 +42,42 @@ extern crate xulstore;
 extern crate jsrust_shared;
 #[cfg(feature = "bitsdownload")]
 extern crate bitsdownload;
 extern crate storage;
 #[cfg(feature = "moz_places")]
 extern crate bookmark_sync;
 extern crate shift_or_euc_c;
 
+extern crate arrayvec;
+
 extern crate audio_thread_priority;
 
 #[cfg(feature = "webrtc")]
 extern crate mdns_service;
 extern crate neqo_glue;
 #[cfg(feature = "webgpu")]
 extern crate wgpu_remote;
 
 #[cfg(feature = "wasm_library_sandboxing")]
 extern crate rlbox_lucet_sandbox;
 
 use std::boxed::Box;
 use std::env;
 use std::ffi::{CStr, CString};
 use std::os::raw::c_char;
-#[cfg(target_os = "android")]
 use std::os::raw::c_int;
 #[cfg(target_os = "android")]
 use log::Level;
 #[cfg(not(target_os = "android"))]
 use log::Log;
+use std::cmp;
+use std::panic;
+use std::ops::Deref;
+use arrayvec::{Array, ArrayString};
 
 extern "C" {
     fn gfx_critical_note(msg: *const c_char);
     #[cfg(target_os = "android")]
     fn __android_log_write(prio: c_int, tag: *const c_char, text: *const c_char) -> c_int;
 }
 
 struct GeckoLogger {
@@ -167,16 +172,103 @@ pub extern "C" fn GkRust_Shutdown() {
 }
 
 /// Used to implement `nsIDebug2::RustPanic` for testing purposes.
 #[no_mangle]
 pub extern "C" fn intentional_panic(message: *const c_char) {
     panic!("{}", unsafe { CStr::from_ptr(message) }.to_string_lossy());
 }
 
+extern "C" {
+    // We can't use MOZ_Crash directly because it may be weakly linked
+    // to libxul, and rust can't handle that.
+    fn GeckoCrash(filename: *const c_char, line: c_int, reason: *const c_char) -> !;
+}
+
+/// Truncate a string at the closest unicode character boundary
+/// ```
+/// assert_eq!(str_truncate_valid("éà", 3), "é");
+/// assert_eq!(str_truncate_valid("éà", 4), "éè");
+/// ```
+fn str_truncate_valid(s: &str, mut mid: usize) -> &str {
+    loop {
+        if let Some(res) = s.get(..mid) {
+            return res;
+        }
+        mid -= 1;
+    }
+}
+
+/// Similar to ArrayString, but with terminating nul character.
+#[derive(Debug, PartialEq)]
+struct ArrayCString<A: Array<Item = u8> + Copy> {
+    inner: ArrayString<A>,
+}
+
+impl<S: AsRef<str>, A: Array<Item = u8> + Copy> From<S> for ArrayCString<A> {
+    /// Contrary to ArrayString::from, truncates at the closest unicode
+    /// character boundary.
+    /// ```
+    /// assert_eq!(ArrayCString::<[_; 4]>::from("éà"),
+    ///            ArrayCString::<[_; 4]>::from("é"));
+    /// assert_eq!(&*ArrayCString::<[_; 4]>::from("éà"), "é\0");
+    /// ```
+    fn from(s: S) -> Self {
+        let s = s.as_ref();
+        let len = cmp::min(s.len(), A::CAPACITY - 1);
+        let mut result = Self {
+            inner: ArrayString::from(str_truncate_valid(s, len)).unwrap(),
+        };
+        result.inner.push('\0');
+        result
+    }
+}
+
+impl<A: Array<Item = u8> + Copy> Deref for ArrayCString<A> {
+    type Target = str;
+
+    fn deref(&self) -> &str {
+        self.inner.as_str()
+    }
+}
+
+fn panic_hook(info: &panic::PanicInfo) {
+    // Try to handle &str/String payloads, which should handle 99% of cases.
+    let payload = info.payload();
+    let message = if let Some(s) = payload.downcast_ref::<&str>() {
+        s
+    } else if let Some(s) = payload.downcast_ref::<String>() {
+        s.as_str()
+    } else {
+        // Not the most helpful thing, but seems unlikely to happen
+        // in practice.
+        "Unhandled rust panic payload!"
+    };
+    let (filename, line) = if let Some(loc) = info.location() {
+        (loc.file(), loc.line())
+    } else {
+        ("unknown.rs", 0)
+    };
+    // Copy the message and filename to the stack in order to safely add
+    // a terminating nul character (since rust strings don't come with one
+    // and GeckoCrash wants one).
+    let message = ArrayCString::<[_; 512]>::from(message);
+    let filename = ArrayCString::<[_; 512]>::from(filename);
+    unsafe {
+        GeckoCrash(filename.as_ptr() as *const c_char, line as c_int,
+                   message.as_ptr() as *const c_char);
+    }
+}
+
+/// Configure a panic hook to redirect rust panics to Gecko's MOZ_Crash.
+#[no_mangle]
+pub extern "C" fn install_rust_panic_hook() {
+    panic::set_hook(Box::new(panic_hook));
+}
+
 #[cfg(feature = "oom_with_hook")]
 mod oom_hook {
     use std::alloc::{Layout, set_alloc_error_hook};
 
     extern "C" {
         fn GeckoHandleOOM(size: usize) -> !;
     }
 
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -5092,16 +5092,22 @@ mozilla::BinPathType XRE_GetChildProcBin
       return BinPathType::PluginContainer;
   }
 }
 
 // Because rust doesn't handle weak symbols, this function wraps the weak
 // malloc_handle_oom for it.
 extern "C" void GeckoHandleOOM(size_t size) { mozalloc_handle_oom(size); }
 
+// Similarly, this wraps MOZ_Crash
+extern "C" void GeckoCrash(const char* aFilename, int aLine,
+                           const char* aReason) {
+  MOZ_Crash(aFilename, aLine, aReason);
+}
+
 // From toolkit/library/rust/shared/lib.rs
 extern "C" void install_rust_panic_hook();
 extern "C" void install_rust_oom_hook();
 
 struct InstallRustHooks {
   InstallRustHooks() {
     install_rust_panic_hook();
     install_rust_oom_hook();