diff options
author | Josh Matthews <josh@joshmatthews.net> | 2017-06-16 09:48:21 -0400 |
---|---|---|
committer | Josh Matthews <josh@joshmatthews.net> | 2017-06-16 17:55:25 -0400 |
commit | b29d0c6c318ab3bede814a97a7dd83ea42d03c7b (patch) | |
tree | 8ae10268df55fa7b463d366f2252ae1a6471a048 /components/script/dom/console.rs | |
parent | 66c130d55aa0d7af1104c00e93a5bf950f23a383 (diff) | |
download | servo-b29d0c6c318ab3bede814a97a7dd83ea42d03c7b.tar.gz servo-b29d0c6c318ab3bede814a97a7dd83ea42d03c7b.zip |
Hold stderr lock when using stdout through Console APIs.
Diffstat (limited to 'components/script/dom/console.rs')
-rw-r--r-- | components/script/dom/console.rs | 102 |
1 files changed, 65 insertions, 37 deletions
diff --git a/components/script/dom/console.rs b/components/script/dom/console.rs index d9df56ebef0..7aa99c2fab6 100644 --- a/components/script/dom/console.rs +++ b/components/script/dom/console.rs @@ -7,6 +7,7 @@ use dom::bindings::inheritance::Castable; use dom::bindings::str::DOMString; use dom::globalscope::GlobalScope; use dom::workerglobalscope::WorkerGlobalScope; +use std::io; // https://developer.mozilla.org/en-US/docs/Web/API/Console pub struct Console(()); @@ -27,74 +28,101 @@ impl Console { } } +// In order to avoid interleaving the stdout output of the Console API methods +// with stderr that could be in use on other threads, we lock stderr until +// we're finished with stdout. Since the stderr lock is reentrant, there is +// no risk of deadlock if the callback ends up trying to write to stderr for +// any reason. +fn with_stderr_lock<F>(f: F) where F: FnOnce() { + let stderr = io::stderr(); + let _handle = stderr.lock(); + f() +} + impl Console { // https://developer.mozilla.org/en-US/docs/Web/API/Console/log pub fn Log(global: &GlobalScope, messages: Vec<DOMString>) { - for message in messages { - println!("{}", message); - Self::send_to_devtools(global, LogLevel::Log, message); - } + with_stderr_lock(move || { + for message in messages { + println!("{}", message); + Self::send_to_devtools(global, LogLevel::Log, message); + } + }) } // https://developer.mozilla.org/en-US/docs/Web/API/Console pub fn Debug(global: &GlobalScope, messages: Vec<DOMString>) { - for message in messages { - println!("{}", message); - Self::send_to_devtools(global, LogLevel::Debug, message); - } + with_stderr_lock(move || { + for message in messages { + println!("{}", message); + Self::send_to_devtools(global, LogLevel::Debug, message); + } + }) } // https://developer.mozilla.org/en-US/docs/Web/API/Console/info pub fn Info(global: &GlobalScope, messages: Vec<DOMString>) { - for message in messages { - println!("{}", message); - Self::send_to_devtools(global, LogLevel::Info, message); - } + with_stderr_lock(move || { + for message in messages { + println!("{}", message); + Self::send_to_devtools(global, LogLevel::Info, message); + } + }) } // https://developer.mozilla.org/en-US/docs/Web/API/Console/warn pub fn Warn(global: &GlobalScope, messages: Vec<DOMString>) { - for message in messages { - println!("{}", message); - Self::send_to_devtools(global, LogLevel::Warn, message); - } + with_stderr_lock(move || { + for message in messages { + println!("{}", message); + Self::send_to_devtools(global, LogLevel::Warn, message); + } + }) } // https://developer.mozilla.org/en-US/docs/Web/API/Console/error pub fn Error(global: &GlobalScope, messages: Vec<DOMString>) { - for message in messages { - println!("{}", message); - Self::send_to_devtools(global, LogLevel::Error, message); - } + with_stderr_lock(move || { + for message in messages { + println!("{}", message); + Self::send_to_devtools(global, LogLevel::Error, message); + } + }) } // https://developer.mozilla.org/en-US/docs/Web/API/Console/assert pub fn Assert(global: &GlobalScope, condition: bool, message: Option<DOMString>) { - if !condition { - let message = message.unwrap_or_else(|| DOMString::from("no message")); - println!("Assertion failed: {}", message); - Self::send_to_devtools(global, LogLevel::Error, message); - } + with_stderr_lock(move || { + if !condition { + let message = message.unwrap_or_else(|| DOMString::from("no message")); + println!("Assertion failed: {}", message); + Self::send_to_devtools(global, LogLevel::Error, message); + } + }) } // https://developer.mozilla.org/en-US/docs/Web/API/Console/time pub fn Time(global: &GlobalScope, label: DOMString) { - if let Ok(()) = global.time(label.clone()) { - let message = DOMString::from(format!("{}: timer started", label)); - println!("{}", message); - Self::send_to_devtools(global, LogLevel::Log, message); - } + with_stderr_lock(move || { + if let Ok(()) = global.time(label.clone()) { + let message = DOMString::from(format!("{}: timer started", label)); + println!("{}", message); + Self::send_to_devtools(global, LogLevel::Log, message); + } + }) } // https://developer.mozilla.org/en-US/docs/Web/API/Console/timeEnd pub fn TimeEnd(global: &GlobalScope, label: DOMString) { - if let Ok(delta) = global.time_end(&label) { - let message = DOMString::from( - format!("{}: {}ms", label, delta) - ); - println!("{}", message); - Self::send_to_devtools(global, LogLevel::Log, message); - }; + with_stderr_lock(move || { + if let Ok(delta) = global.time_end(&label) { + let message = DOMString::from( + format!("{}: {}ms", label, delta) + ); + println!("{}", message); + Self::send_to_devtools(global, LogLevel::Log, message); + }; + }) } } |