aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/console.rs
diff options
context:
space:
mode:
authorJosh Matthews <josh@joshmatthews.net>2017-06-16 09:48:21 -0400
committerJosh Matthews <josh@joshmatthews.net>2017-06-16 17:55:25 -0400
commitb29d0c6c318ab3bede814a97a7dd83ea42d03c7b (patch)
tree8ae10268df55fa7b463d366f2252ae1a6471a048 /components/script/dom/console.rs
parent66c130d55aa0d7af1104c00e93a5bf950f23a383 (diff)
downloadservo-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.rs102
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);
+ };
+ })
}
}