From 27186751913beb7b81220404ea4cf58fac6f2d0d Mon Sep 17 00:00:00 2001 From: Paul Rouget Date: Fri, 2 Nov 2018 10:40:59 +0100 Subject: [PATCH] Count threads at shutdown and warn if not all finished --- Cargo.lock | 1 + components/config/opts.rs | 10 +++++++ ports/servo/Cargo.toml | 3 ++ ports/servo/build.rs | 9 ++++++ ports/servo/platform/macos/count_threads.c | 13 +++++++++ ports/servo/platform/macos/mod.rs | 32 +++++++++++++++++++++- 6 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 ports/servo/platform/macos/count_threads.c diff --git a/Cargo.lock b/Cargo.lock index 1058bfdac39..255496ac726 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3210,6 +3210,7 @@ version = "0.0.1" dependencies = [ "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-channel 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", "gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/components/config/opts.rs b/components/config/opts.rs index 2d16d823030..b36cb817d42 100644 --- a/components/config/opts.rs +++ b/components/config/opts.rs @@ -226,6 +226,9 @@ pub struct Opts { /// Print Progressive Web Metrics to console. pub print_pwm: bool, + + /// Only shutdown once all theads are finished. + pub clean_shutdown: bool, } fn print_usage(app: &str, opts: &Options) { @@ -600,6 +603,7 @@ pub fn default_opts() -> Opts { certificate_path: None, unminify_js: false, print_pwm: false, + clean_shutdown: false, } } @@ -752,6 +756,11 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult { "config directory following xdg spec on linux platform", "", ); + opts.optflag( + "", + "clean-shutdown", + "Do not shutdown until all threads have finished (macos only)", + ); opts.optflag("v", "version", "Display servo version information"); opts.optflag("", "unminify-js", "Unminify Javascript"); opts.optopt("", "profiler-db-user", "Profiler database user", ""); @@ -1035,6 +1044,7 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult { certificate_path: opt_match.opt_str("certificate-path"), unminify_js: opt_match.opt_present("unminify-js"), print_pwm: opt_match.opt_present("print-pwm"), + clean_shutdown: opt_match.opt_present("clean-shutdown"), }; set_defaults(opts); diff --git a/ports/servo/Cargo.toml b/ports/servo/Cargo.toml index 8c54307c03a..057d7bcae87 100644 --- a/ports/servo/Cargo.toml +++ b/ports/servo/Cargo.toml @@ -16,6 +16,9 @@ bench = false [target.'cfg(windows)'.build-dependencies] winres = "0.1" +[target.'cfg(target_os = "macos")'.build-dependencies] +cc = "1.0" + [package.metadata.winres] FileDescription = "Servo" LegalCopyright = "© The Servo Project Developers" diff --git a/ports/servo/build.rs b/ports/servo/build.rs index f7e7f49c919..4e4aa243196 100644 --- a/ports/servo/build.rs +++ b/ports/servo/build.rs @@ -2,6 +2,9 @@ * 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/. */ +#[cfg(target_os = "macos")] +extern crate cc; + #[cfg(windows)] extern crate winres; @@ -13,4 +16,10 @@ fn main() { res.set_manifest_file("platform/windows/servo.exe.manifest"); res.compile().unwrap(); } + #[cfg(target_os = "macos")] + { + cc::Build::new() + .file("platform/macos/count_threads.c") + .compile("count_threads"); + } } diff --git a/ports/servo/platform/macos/count_threads.c b/ports/servo/platform/macos/count_threads.c new file mode 100644 index 00000000000..04b7c0bc839 --- /dev/null +++ b/ports/servo/platform/macos/count_threads.c @@ -0,0 +1,13 @@ +/* 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/. */ + +#include + +int macos_count_running_threads() { + task_t task = current_task(); + thread_act_array_t threads; + mach_msg_type_number_t tcnt; + task_threads(task, &threads, &tcnt); + return tcnt; +} diff --git a/ports/servo/platform/macos/mod.rs b/ports/servo/platform/macos/mod.rs index 9aaa63b8a1a..55d7fa23443 100644 --- a/ports/servo/platform/macos/mod.rs +++ b/ports/servo/platform/macos/mod.rs @@ -2,7 +2,10 @@ * 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 servo::config::opts; use std::ptr; +use std::thread; +use std::time::Duration; pub fn deinit() { // An unfortunate hack to make sure the linker's dead code stripping doesn't strip our @@ -10,9 +13,36 @@ pub fn deinit() { unsafe { ptr::read_volatile(&INFO_PLIST[0]); } + + let thread_count = unsafe { + macos_count_running_threads() + }; + + if thread_count != 1 { + println!("{} threads are still running after shutdown (bad).", thread_count); + if opts::get().clean_shutdown { + println!("Waiting until all threads have shutdown"); + loop { + let thread_count = unsafe { + macos_count_running_threads() + }; + if thread_count == 1 { + break; + } + thread::sleep(Duration::from_millis(1000)); + println!("{} threads are still running.", thread_count); + } + } + } else { + println!("All threads have shutdown (good)."); + } } -#[cfg(target_os = "macos")] #[link_section = "__TEXT,__info_plist"] #[no_mangle] pub static INFO_PLIST: [u8; 619] = *include_bytes!("Info.plist"); + +#[link(name = "count_threads")] +extern { + fn macos_count_running_threads() -> i32; +}