Bug 1456350 - Forward webrender error log to gfxCriticalNote r=bholley
authorsotaro <sotaro.ikeda.g@gmail.com>
Fri, 27 Apr 2018 16:48:39 +0900
changeset 472123 56a2a8cc35fd988715fdb07a8efd6806560284a5
parent 472102 4b0e963b050b63441999b49a23cc03b6e4406cd5
child 472124 1893ddb56c3b2c4264cae95ae53139cd769330bf
push id1728
push userjlund@mozilla.com
push dateMon, 18 Jun 2018 21:12:27 +0000
treeherdermozilla-release@c296fde26f5f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbholley
bugs1456350
milestone61.0a1
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
Bug 1456350 - Forward webrender error log to gfxCriticalNote r=bholley
Cargo.lock
servo/ports/geckolib/Cargo.toml
servo/ports/geckolib/glue.rs
servo/ports/geckolib/lib.rs
servo/ports/geckolib/tests/lib.rs
toolkit/library/rust/shared/Cargo.toml
toolkit/library/rust/shared/lib.rs
xpcom/build/XPCOMInit.cpp
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -781,17 +781,16 @@ dependencies = [
 
 [[package]]
 name = "geckoservo"
 version = "0.0.1"
 dependencies = [
  "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.23.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "cstr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "malloc_size_of 0.0.1",
  "nsstring 0.1.0",
  "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "selectors 0.19.0",
  "servo_arc 0.1.1",
  "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -823,18 +822,19 @@ version = "0.1.0"
 dependencies = [
  "audioipc-client 0.4.0",
  "audioipc-server 0.2.3",
  "cose-c 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "cubeb-pulse 0.2.0",
  "cubeb-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "encoding_c 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "encoding_glue 0.1.0",
+ "env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "geckoservo 0.0.1",
- "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "mozurl 0.0.1",
  "mp4parse_capi 0.10.1",
  "netwerk_helper 0.0.1",
  "nserror 0.1.0",
  "nsstring 0.1.0",
  "prefs_parser 0.0.1",
  "rsdparsa_capi 0.1.0",
  "u2fhid 0.1.0",
--- a/servo/ports/geckolib/Cargo.toml
+++ b/servo/ports/geckolib/Cargo.toml
@@ -12,17 +12,16 @@ crate-type = ["staticlib", "rlib"]
 [features]
 bindgen = ["style/use_bindgen"]
 gecko_debug = ["style/gecko_debug"]
 
 [dependencies]
 atomic_refcell = "0.1"
 cssparser = "0.23.0"
 cstr = "0.1.2"
-env_logger = {version = "0.5", default-features = false} # disable `regex` to reduce code size
 libc = "0.2"
 log = {version = "0.4", features = ["release_max_level_info"]}
 malloc_size_of = {path = "../../components/malloc_size_of"}
 nsstring = {path = "../../support/gecko/nsstring"}
 parking_lot = "0.5"
 selectors = {path = "../../components/selectors"}
 servo_arc = {path = "../../components/servo_arc"}
 smallvec = "0.6"
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -1,23 +1,21 @@
 /* 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 cssparser::{ParseErrorKind, Parser, ParserInput, SourceLocation};
 use cssparser::ToCss as ParserToCss;
-use env_logger::Builder;
 use malloc_size_of::MallocSizeOfOps;
 use nsstring::nsCString;
 use selectors::{NthIndexCache, SelectorList};
 use selectors::matching::{MatchingContext, MatchingMode, matches_selector};
 use servo_arc::{Arc, ArcBorrow, RawOffsetArc};
 use smallvec::SmallVec;
 use std::cell::RefCell;
-use std::env;
 use std::fmt::Write;
 use std::iter;
 use std::mem;
 use std::os::raw::c_void;
 use std::ptr;
 use style::applicable_declarations::ApplicableDeclarationBlock;
 use style::author_styles::AuthorStyles;
 use style::context::{CascadeInputs, QuirksMode, SharedStyleContext, StyleContext};
@@ -179,24 +177,16 @@ use super::stylesheet_loader::{AsyncStyl
 // A dummy url data for where we don't pass url data in.
 // We need to get rid of this sooner than later.
 static mut DUMMY_URL_DATA: *mut URLExtraData = 0 as *mut URLExtraData;
 
 #[no_mangle]
 pub extern "C" fn Servo_Initialize(dummy_url_data: *mut URLExtraData) {
     use style::gecko_bindings::sugar::origin_flags;
 
-    // Initialize logging.
-    let mut builder = Builder::new();
-    let default_level = if cfg!(debug_assertions) { "warn" } else { "error" };
-    match env::var("RUST_LOG") {
-      Ok(v) => builder.parse(&v).init(),
-      _ => builder.parse(default_level).init(),
-    };
-
     // Pretend that we're a Servo Layout thread, to make some assertions happy.
     thread_state::initialize(thread_state::ThreadState::LAYOUT);
 
     // Perform some debug-only runtime assertions.
     restyle_hints::assert_restyle_hints_match();
     origin_flags::assert_flags_match();
     parser::assert_parsing_mode_match();
     traversal_flags::assert_traversal_flags_match();
--- a/servo/ports/geckolib/lib.rs
+++ b/servo/ports/geckolib/lib.rs
@@ -1,16 +1,15 @@
 /* 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/. */
 
 
 extern crate cssparser;
 #[macro_use] extern crate cstr;
-extern crate env_logger;
 extern crate libc;
 #[macro_use] extern crate log;
 extern crate malloc_size_of;
 extern crate nsstring;
 extern crate selectors;
 extern crate servo_arc;
 extern crate smallvec;
 #[macro_use] extern crate style;
--- a/servo/ports/geckolib/tests/lib.rs
+++ b/servo/ports/geckolib/tests/lib.rs
@@ -9,17 +9,16 @@
 // On Linux and OS X linking succeeds anyway.
 // Presumably these symbol declarations don’t need to be resolved
 // as they’re not used in any code called from this crate.
 #![cfg(any(linking_with_gecko, not(windows)))]
 
 extern crate atomic_refcell;
 extern crate cssparser;
 #[macro_use] extern crate cstr;
-extern crate env_logger;
 extern crate geckoservo;
 #[macro_use] extern crate log;
 extern crate malloc_size_of;
 extern crate selectors;
 extern crate smallvec;
 #[macro_use] extern crate size_of_test;
 #[macro_use] extern crate style;
 extern crate style_traits;
--- a/toolkit/library/rust/shared/Cargo.toml
+++ b/toolkit/library/rust/shared/Cargo.toml
@@ -19,17 +19,18 @@ cubeb-pulse = { path = "../../../../medi
 cubeb-sys = { version = "0.5.0", optional = true, features=["gecko-in-tree"] }
 encoding_c = "0.8.0"
 encoding_glue = { path = "../../../../intl/encoding_glue" }
 audioipc-client = { path = "../../../../media/audioipc/client", optional = true }
 audioipc-server = { path = "../../../../media/audioipc/server", optional = true }
 u2fhid = { path = "../../../../dom/webauthn/u2f-hid-rs" }
 rsdparsa_capi = { path = "../../../../media/webrtc/signaling/src/sdp/rsdparsa_capi" }
 # We have these to enforce common feature sets for said crates.
-log = {version = "0.3", features = ["release_max_level_info"]}
+log = {version = "0.4", features = ["release_max_level_info"]}
+env_logger = {version = "0.5", default-features = false} # disable `regex` to reduce code size
 cose-c = { version = "0.1.5" }
 
 [features]
 default = []
 bindgen = ["geckoservo/bindgen"]
 servo = ["geckoservo"]
 quantum_render = ["webrender_bindings"]
 cubeb-remoting = ["cubeb-sys", "audioipc-client", "audioipc-server"]
--- a/toolkit/library/rust/shared/lib.rs
+++ b/toolkit/library/rust/shared/lib.rs
@@ -17,27 +17,99 @@ extern crate webrender_bindings;
 #[cfg(feature = "cubeb_pulse_rust")]
 extern crate cubeb_pulse;
 extern crate encoding_c;
 extern crate encoding_glue;
 #[cfg(feature = "cubeb-remoting")]
 extern crate audioipc_client;
 #[cfg(feature = "cubeb-remoting")]
 extern crate audioipc_server;
+extern crate env_logger;
 extern crate u2fhid;
 extern crate log;
 extern crate cosec;
 extern crate rsdparsa_capi;
 
 use std::boxed::Box;
-use std::ffi::CStr;
+use std::env;
+use std::ffi::{CStr, CString};
 use std::os::raw::c_char;
 use std::panic;
 
+extern "C" {
+    fn gfx_critical_note(msg: *const c_char);
+}
 
+struct GeckoLogger {
+    logger: env_logger::Logger
+}
+
+impl GeckoLogger {
+    fn new() -> GeckoLogger {
+        let mut builder = env_logger::Builder::new();
+        let default_level = if cfg!(debug_assertions) { "warn" } else { "error" };
+        let logger = match env::var("RUST_LOG") {
+            Ok(v) => builder.parse(&v).build(),
+            _ => builder.parse(default_level).build(),
+        };
+
+        GeckoLogger {
+            logger
+        }
+    }
+
+    fn init() -> Result<(), log::SetLoggerError> {
+        let gecko_logger = Self::new();
+
+        log::set_max_level(gecko_logger.logger.filter());
+        log::set_boxed_logger(Box::new(gecko_logger))
+    }
+
+    fn should_log_to_gfx_critical_note(record: &log::Record) -> bool {
+        if record.level() == log::Level::Error &&
+           record.target().contains("webrender") {
+            true
+        } else {
+            false
+        }
+    }
+
+    fn maybe_log_to_gfx_critical_note(&self, record: &log::Record) {
+        if Self::should_log_to_gfx_critical_note(record) {
+            let msg = CString::new(format!("{}", record.args())).unwrap();
+            unsafe {
+                gfx_critical_note(msg.as_ptr());
+            }
+        }
+    }
+}
+
+impl log::Log for GeckoLogger {
+    fn enabled(&self, metadata: &log::Metadata) -> bool {
+        self.logger.enabled(metadata)
+    }
+
+    fn log(&self, record: &log::Record) {
+        // Forward log to gfxCriticalNote, if the log should be in gfx crash log.
+        self.maybe_log_to_gfx_critical_note(record);
+        self.logger.log(record);
+    }
+
+    fn flush(&self) { }
+}
+
+#[no_mangle]
+pub extern "C" fn GkRust_Init() {
+    // Initialize logging.
+    let _ = GeckoLogger::init();
+}
+
+#[no_mangle]
+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());
 }
 
 /// Contains the panic message, if set.
--- a/xpcom/build/XPCOMInit.cpp
+++ b/xpcom/build/XPCOMInit.cpp
@@ -151,16 +151,20 @@ extern nsresult nsStringInputStreamConst
 #include "js/Initialization.h"
 
 #include "gfxPlatform.h"
 
 using namespace mozilla;
 using base::AtExitManager;
 using mozilla::ipc::BrowserProcessSubThread;
 
+// From toolkit/library/rust/lib.rs
+extern "C" void GkRust_Init();
+extern "C" void GkRust_Shutdown();
+
 namespace {
 
 static AtExitManager* sExitManager;
 static MessageLoop* sMessageLoop;
 static bool sCommandLineWasInitialized;
 static BrowserProcessSubThread* sIOThread;
 static BackgroundHangMonitor* sMainHangMonitor;
 
@@ -447,16 +451,18 @@ NS_InitXPCOM2(nsIServiceManager** aResul
 
   NS_InitAtomTable();
 
   // We don't have the arguments by hand here.  If logging has already been
   // initialized by a previous call to LogModule::Init with the arguments
   // passed, passing (0, nullptr) is alright here.
   mozilla::LogModule::Init(0, nullptr);
 
+  GkRust_Init();
+
   nsresult rv = NS_OK;
 
   // We are not shutting down
   gXPCOMShuttingDown = false;
 
   // Initialize the available memory tracker before other threads have had a
   // chance to start up, because the initialization is not thread-safe.
   mozilla::AvailableMemoryTracker::Init();
@@ -994,16 +1000,18 @@ ShutdownXPCOM(nsIServiceManager* aServMg
     NS_ASSERTION(cnt == 0, "Component Manager being held past XPCOM shutdown.");
   }
   nsComponentManagerImpl::gComponentManager = nullptr;
   nsCategoryManager::Destroy();
 
   // Shut down SystemGroup for main thread dispatching.
   SystemGroup::Shutdown();
 
+  GkRust_Shutdown();
+
   NS_ShutdownAtomTable();
 
   NS_IF_RELEASE(gDebug);
 
   delete sIOThread;
   sIOThread = nullptr;
 
   delete sMessageLoop;