diff --git a/Cargo.lock b/Cargo.lock index 94554fe38..3c0fcfdee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -53,12 +53,6 @@ dependencies = [ "vector_utils", ] -[[package]] -name = "anstyle" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" - [[package]] name = "anyhow" version = "1.0.63" @@ -83,21 +77,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbf56136a5198c7b01a49e3afcbef6cf84597273d298f54432926024107b0109" -[[package]] -name = "assert_cmd" -version = "2.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88903cb14723e4d4003335bb7f8a14f27691649105346a0f0957466c096adfe6" -dependencies = [ - "anstyle", - "bstr", - "doc-comment", - "predicates", - "predicates-core", - "predicates-tree", - "wait-timeout", -] - [[package]] name = "attohttpc" version = "0.26.1" @@ -206,22 +185,11 @@ dependencies = [ "wyhash", ] -[[package]] -name = "bstr" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05" -dependencies = [ - "memchr", - "regex-automata", - "serde", -] - [[package]] name = "build_enclone_proto" version = "0.5.219" dependencies = [ - "prost-build 0.11.9", + "prost-build", "tempfile", ] @@ -285,15 +253,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "cpp_demangle" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8227005286ec39567949b33df9896bcadfa6051bccca2488129f108ca23119" -dependencies = [ - "cfg-if", -] - [[package]] name = "cpufeatures" version = "0.2.6" @@ -395,15 +354,6 @@ dependencies = [ "smallvec", ] -[[package]] -name = "debugid" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" -dependencies = [ - "uuid", -] - [[package]] name = "deranged" version = "0.3.11" @@ -421,12 +371,6 @@ dependencies = [ "syn 1.0.105", ] -[[package]] -name = "difflib" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" - [[package]] name = "digest" version = "0.10.3" @@ -441,12 +385,6 @@ dependencies = [ name = "dna" version = "0.1.3" -[[package]] -name = "doc-comment" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" - [[package]] name = "either" version = "1.8.0" @@ -459,7 +397,6 @@ version = "0.5.219" dependencies = [ "amino", "ansi_escape", - "assert_cmd", "debruijn", "enclone_core", "enclone_proto", @@ -471,7 +408,6 @@ dependencies = [ "pager", "perf_stats", "petgraph", - "pretty_trace", "qd", "rayon", "stats_utils", @@ -570,7 +506,7 @@ version = "0.5.219" dependencies = [ "bio_edit", "byteorder", - "prost 0.11.9", + "prost", "serde", "thiserror", "vdj_ann", @@ -624,7 +560,6 @@ version = "0.5.219" dependencies = [ "io_utils", "itertools", - "pretty_trace", "string_utils", "vector_utils", ] @@ -725,18 +660,6 @@ dependencies = [ "windows-sys", ] -[[package]] -name = "findshlibs" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40b9e59cd0f7e0806cca4be089683ecb6434e602038df21fe6bf6711b2f07f64" -dependencies = [ - "cc", - "lazy_static", - "libc", - "winapi", -] - [[package]] name = "fixedbitset" version = "0.4.2" @@ -1138,15 +1061,6 @@ version = "2.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" -[[package]] -name = "memmap2" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe751422e4a8caa417e13c3ea66452215d7d63e19e604f4980461212f3ae1322" -dependencies = [ - "libc", -] - [[package]] name = "memoffset" version = "0.6.5" @@ -1213,29 +1127,6 @@ dependencies = [ "rawpointer", ] -[[package]] -name = "nix" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "195cdbc1741b8134346d515b3a56a1c94b0912758009cfd53f99ea0f57b065fc" -dependencies = [ - "bitflags", - "cfg-if", - "libc", - "memoffset", -] - -[[package]] -name = "nix" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" -dependencies = [ - "bitflags", - "cfg-if", - "libc", -] - [[package]] name = "num-bigint" version = "0.4.4" @@ -1388,81 +1279,12 @@ version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" -[[package]] -name = "pprof" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef5c97c51bd34c7e742402e216abdeb44d415fbe6ae41d56b114723e953711cb" -dependencies = [ - "backtrace", - "cfg-if", - "findshlibs", - "libc", - "log", - "nix 0.26.4", - "once_cell", - "parking_lot", - "prost 0.12.3", - "prost-build 0.12.3", - "prost-derive 0.12.3", - "sha2", - "smallvec", - "symbolic-demangle", - "tempfile", - "thiserror", -] - [[package]] name = "ppv-lite86" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" -[[package]] -name = "predicates" -version = "3.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09963355b9f467184c04017ced4a2ba2d75cbcb4e7462690d388233253d4b1a9" -dependencies = [ - "anstyle", - "difflib", - "itertools", - "predicates-core", -] - -[[package]] -name = "predicates-core" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174" - -[[package]] -name = "predicates-tree" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d86de6de25020a36c6d3643a86d9a6a9f552107c0559c60ea03551b5e16c032" -dependencies = [ - "predicates-core", - "termtree", -] - -[[package]] -name = "pretty_trace" -version = "0.5.24" -dependencies = [ - "backtrace", - "io_utils", - "lazy_static", - "libc", - "nix 0.24.2", - "pprof", - "rayon", - "stats_utils", - "string_utils", - "tables", - "vector_utils", -] - [[package]] name = "prettyplease" version = "0.1.25" @@ -1473,16 +1295,6 @@ dependencies = [ "syn 1.0.105", ] -[[package]] -name = "prettyplease" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" -dependencies = [ - "proc-macro2", - "syn 2.0.52", -] - [[package]] name = "proc-macro-error" version = "1.0.4" @@ -1522,17 +1334,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" dependencies = [ "bytes", - "prost-derive 0.11.9", -] - -[[package]] -name = "prost" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a" -dependencies = [ - "bytes", - "prost-derive 0.12.3", + "prost-derive", ] [[package]] @@ -1548,37 +1350,15 @@ dependencies = [ "log", "multimap", "petgraph", - "prettyplease 0.1.25", - "prost 0.11.9", - "prost-types 0.11.9", + "prettyplease", + "prost", + "prost-types", "regex", "syn 1.0.105", "tempfile", "which", ] -[[package]] -name = "prost-build" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" -dependencies = [ - "bytes", - "heck", - "itertools", - "log", - "multimap", - "once_cell", - "petgraph", - "prettyplease 0.2.16", - "prost 0.12.3", - "prost-types 0.12.3", - "regex", - "syn 2.0.52", - "tempfile", - "which", -] - [[package]] name = "prost-derive" version = "0.11.9" @@ -1592,35 +1372,13 @@ dependencies = [ "syn 1.0.105", ] -[[package]] -name = "prost-derive" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" -dependencies = [ - "anyhow", - "itertools", - "proc-macro2", - "quote", - "syn 2.0.52", -] - [[package]] name = "prost-types" version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" dependencies = [ - "prost 0.11.9", -] - -[[package]] -name = "prost-types" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "193898f59edcf43c26227dcd4c8427f00d99d61e95dcde58dabd49fa291d470e" -dependencies = [ - "prost 0.12.3", + "prost", ] [[package]] @@ -1917,12 +1675,6 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - [[package]] name = "statrs" version = "0.16.0" @@ -1978,29 +1730,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab16ced94dbd8a46c82fd81e3ed9a8727dac2977ea869d217bcc4ea1f122e81f" -[[package]] -name = "symbolic-common" -version = "12.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cccfffbc6bb3bb2d3a26cd2077f4d055f6808d266f9d4d158797a4c60510dfe" -dependencies = [ - "debugid", - "memmap2", - "stable_deref_trait", - "uuid", -] - -[[package]] -name = "symbolic-demangle" -version = "12.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76a99812da4020a67e76c4eb41f08c87364c14170495ff780f30dd519c221a68" -dependencies = [ - "cpp_demangle", - "rustc-demangle", - "symbolic-common", -] - [[package]] name = "syn" version = "1.0.105" @@ -2056,12 +1785,6 @@ dependencies = [ "windows-sys", ] -[[package]] -name = "termtree" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "507e9898683b6c43a9aa55b64259b721b52ba226e0f3779137e50ad114a4c90b" - [[package]] name = "thiserror" version = "1.0.38" @@ -2187,12 +1910,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "uuid" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" - [[package]] name = "vdj_ann" version = "0.4.4" @@ -2224,7 +1941,6 @@ dependencies = [ "flate2", "io_utils", "perf_stats", - "pretty_trace", "sha2", "string_utils", "vdj_ann", @@ -2253,15 +1969,6 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "wait-timeout" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" -dependencies = [ - "libc", -] - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index c918991eb..ad02ea8bf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,6 @@ members = [ "kmer_lookup", "load_feature_bc", "perf_stats", - "pretty_trace", "stats_utils", "stirling_numbers", "string_utils", diff --git a/GUIDE b/GUIDE index 57a3095a6..d603966cb 100644 --- a/GUIDE +++ b/GUIDE @@ -18,7 +18,6 @@ enclone_tail last part of the code enclone_tools miscellaneous binaries enclone_vars variable definitions enclone_version determine current version string -enclone_visual experimental GUI client credits credits fonts DejaVuSansMono, in case not otherwise available diff --git a/align_tools/README.md b/align_tools/README.md deleted file mode 100644 index 4cad8e1d5..000000000 --- a/align_tools/README.md +++ /dev/null @@ -1,2 +0,0 @@ -This crate contains utilities that are used by the crate -pretty_trace. In time the contents of this crate may be documented, but for now, we recommend against directly using them, as they may be changed. diff --git a/amino/README.md b/amino/README.md deleted file mode 100644 index 4cad8e1d5..000000000 --- a/amino/README.md +++ /dev/null @@ -1,2 +0,0 @@ -This crate contains utilities that are used by the crate -pretty_trace. In time the contents of this crate may be documented, but for now, we recommend against directly using them, as they may be changed. diff --git a/ansi_escape/README.md b/ansi_escape/README.md deleted file mode 100644 index 4cad8e1d5..000000000 --- a/ansi_escape/README.md +++ /dev/null @@ -1,2 +0,0 @@ -This crate contains utilities that are used by the crate -pretty_trace. In time the contents of this crate may be documented, but for now, we recommend against directly using them, as they may be changed. diff --git a/enclone/Cargo.toml b/enclone/Cargo.toml index b1cd96e1f..d0f152657 100644 --- a/enclone/Cargo.toml +++ b/enclone/Cargo.toml @@ -32,7 +32,6 @@ io_utils = { path = "../io_utils" } itertools.workspace = true perf_stats = { path = "../perf_stats" } petgraph = "0.6" -pretty_trace = { path = "../pretty_trace" } qd = { git = "https://github.com/Barandis/qd" } rayon = "1" stats_utils = { path = "../stats_utils" } @@ -40,9 +39,6 @@ string_utils = { path = "../string_utils" } vdj_ann = { path = "../vdj_ann" } vector_utils = { path = "../vector_utils" } -[dev-dependencies] -assert_cmd = "2" - [target.'cfg(not(windows))'.dependencies] pager = "0.16" diff --git a/enclone/src/UNDOC_OPTIONS b/enclone/src/UNDOC_OPTIONS index e6075bf4a..9ed7dba7a 100644 --- a/enclone/src/UNDOC_OPTIONS +++ b/enclone/src/UNDOC_OPTIONS @@ -271,9 +271,6 @@ NO_UNCAP_SIM: turn off uncapping simulation HAPS_DEBUG: turn on debug mode for the HAPS option -PROFILE: turn on profiling, normally used with NOPRINT; paging is turned off because this -This won't work with paging, however you can pipe to "less -r". - =================================================================================================== ROW_FILL_VERBOSE: special option for debugging diff --git a/enclone/src/bin/traceback1.rs b/enclone/src/bin/traceback1.rs deleted file mode 100644 index 478761c23..000000000 --- a/enclone/src/bin/traceback1.rs +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) 2021 10X Genomics, Inc. All rights reserved. - -// Check that an out-of-range reference within a rayon parallel loop yields a correct traceback. -// Make sure that line 17 stays as line 17. Otherwise change the reference to traceback1.rs:17. -// -// This was originally engineered without PrettyTrace, but the problem with this was that if the -// test failed, you get a godawful mess that is impossible to distangle. - -use pretty_trace::PrettyTrace; -use rayon::prelude::*; - -fn main() { - PrettyTrace::new().on(); - let z = vec![0; 100]; - let mut x = vec![0; 100]; - x.par_iter_mut().for_each(|r| { - let _ = z[100 + *r]; // line 17!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - }); -} - -#[test] -fn test_traceback1() { - use assert_cmd; - use assert_cmd::prelude::*; - use std::fmt::Write; - use std::{env, process::Command}; - let mut cmd = Command::cargo_bin("traceback1").expect( - "\nAttempt to run traceback1 failed. The most likely explanation for this is that\n\ - somehow you did not run \"cargo b\". Please try that now, and be sure you are doing\n\ - it from the top-level enclone directory.\n", - ); - let cmd = cmd - .output() - .unwrap_or_else(|_| panic!("{}", "very strange, failed to execute test_traceback1")); - let morsel = "traceback1.rs:17"; - let err = std::str::from_utf8(&cmd.stderr).unwrap(); - if !err.contains(morsel) { - let mut head = String::new(); - let lines = err.split('\n').collect::>(); - const MAX_LINES: usize = 60; - for &line in lines.iter().take(MAX_LINES) { - writeln!(head, "{line}").unwrap(); - } - eprint!( - "\n▓▓▓ test_traceback1 failed because did not find {} as expected;\n\n\ - this was using enclone version {} \n\n\ - ▓▓▓ traceback begins with\n{}", - morsel, - env!("CARGO_PKG_VERSION"), - head, - ); - std::process::exit(1); - } -} diff --git a/enclone/src/bin/update_enclone_binary.rs b/enclone/src/bin/update_enclone_binary.rs index b70da8b24..0f85d9ae2 100644 --- a/enclone/src/bin/update_enclone_binary.rs +++ b/enclone/src/bin/update_enclone_binary.rs @@ -5,7 +5,7 @@ use enclone_core::defs::get_config; use io_utils::path_exists; -use pretty_trace::PrettyTrace; + use std::collections::HashMap; use std::env; @@ -13,7 +13,6 @@ use std::env; use std::os::unix::fs::PermissionsExt; fn main() { - PrettyTrace::new().on(); let mut config = HashMap::::new(); let mut config_file = String::new(); for (key, value) in env::vars() { diff --git a/enclone_args/src/proc_args.rs b/enclone_args/src/proc_args.rs index e81380f62..6a2552356 100644 --- a/enclone_args/src/proc_args.rs +++ b/enclone_args/src/proc_args.rs @@ -504,7 +504,6 @@ pub fn proc_args(ctl: &mut EncloneControl, args: &[String]) -> Result<(), String ("UTR_CON", &mut ctl.gen_opt.utr_con), ("VDUP", &mut ctl.clono_filt_opt.vdup), ("VIS_DUMP", &mut ctl.gen_opt.vis_dump), - ("VISUAL", &mut ctl.visual_mode), ("WEAK", &mut ctl.gen_opt.weak), ("WHITEF", &mut ctl.clono_filt_opt_def.whitef), ]; @@ -650,7 +649,6 @@ pub fn proc_args(ctl: &mut EncloneControl, args: &[String]) -> Result<(), String "COMP", "COMPE", "COMP2", - "CTRLC", "DUMP_INTERNAL_IDS", "EVIL_EYE", "FORCE_EXTERNAL", @@ -667,7 +665,6 @@ pub fn proc_args(ctl: &mut EncloneControl, args: &[String]) -> Result<(), String "PLAIN", "PRINT_CPU", "PRINT_CPU_INFO", - "PROFILE", "SVG", ]; @@ -939,14 +936,6 @@ pub fn proc_args(ctl: &mut EncloneControl, args: &[String]) -> Result<(), String } } - // Force visual mode if plot file is gui or if VIS_DUMP was invoked. - - if (ctl.plot_opt.plot_file == "gui" || ctl.plot_opt.plot_file == "gui_stdout") - && !ctl.gen_opt.vis_dump - { - ctl.visual_mode = true; - } - // Record time. ctl.perf_stats(&targs, "in main args loop"); diff --git a/enclone_args/src/proc_args2.rs b/enclone_args/src/proc_args2.rs index 80d2d0ba3..5b8935607 100644 --- a/enclone_args/src/proc_args2.rs +++ b/enclone_args/src/proc_args2.rs @@ -203,7 +203,7 @@ pub fn proc_args_tail(ctl: &mut EncloneControl, args: &[String]) -> Result<(), S // Get origin descriptions. Flaky and particularly flaky when internal origin args are paths, // since it will look in outs for the file. - if ctl.gen_opt.internal_run || ctl.gen_opt.descrip || ctl.visual_mode || ctl.gen_opt.vis_dump { + if ctl.gen_opt.internal_run || ctl.gen_opt.descrip || ctl.gen_opt.vis_dump { ctl.origin_info.descrips.clear(); let mut results = vec![(0, "".to_string()); ctl.origin_info.n()]; for i in 0..ctl.origin_info.n() { diff --git a/enclone_core/src/defs.rs b/enclone_core/src/defs.rs index c77f2e987..5dabd4976 100644 --- a/enclone_core/src/defs.rs +++ b/enclone_core/src/defs.rs @@ -207,7 +207,6 @@ pub struct GeneralOpt { pub subset_json: String, pub fold_headers: bool, pub no_uncap_sim: bool, - pub profile: bool, pub nopager: bool, pub info: Option, pub info_fields: Vec, @@ -513,30 +512,29 @@ pub struct PerfOpt { #[derive(Default)] pub struct EncloneControl { - pub visual_mode: bool, // running as enclone visual - pub perf_opt: PerfOpt, // computational performance options - pub start_time: Option, // enclone start time - pub gen_opt: GeneralOpt, // miscellaneous general options - pub plot_opt: PlotOpt, // plot options - pub pretty: bool, // use escape characters to enhance view - pub nogray: bool, // don't gray in per cell lines - pub silent: bool, // turn off extra logging - pub force: bool, // make joins even if redundant - pub debug_table_printing: bool, // turn on debugging for table printing - pub merge_all_impropers: bool, // merge all improper exact subclonotypes - pub heur: ClonotypeHeuristics, // algorithmic heuristics - pub origin_info: OriginInfo, // origin (sample) info - pub allele_alg_opt: AlleleAlgOpt, // algorithmic options for allele finding - pub allele_print_opt: AllelePrintOpt, // print options for allele finding - pub join_alg_opt: JoinAlgOpt, // algorithmic options for join - pub join_print_opt: JoinPrintOpt, // printing options for join operations + pub perf_opt: PerfOpt, // computational performance options + pub start_time: Option, // enclone start time + pub gen_opt: GeneralOpt, // miscellaneous general options + pub plot_opt: PlotOpt, // plot options + pub pretty: bool, // use escape characters to enhance view + pub nogray: bool, // don't gray in per cell lines + pub silent: bool, // turn off extra logging + pub force: bool, // make joins even if redundant + pub debug_table_printing: bool, // turn on debugging for table printing + pub merge_all_impropers: bool, // merge all improper exact subclonotypes + pub heur: ClonotypeHeuristics, // algorithmic heuristics + pub origin_info: OriginInfo, // origin (sample) info + pub allele_alg_opt: AlleleAlgOpt, // algorithmic options for allele finding + pub allele_print_opt: AllelePrintOpt, // print options for allele finding + pub join_alg_opt: JoinAlgOpt, // algorithmic options for join + pub join_print_opt: JoinPrintOpt, // printing options for join operations pub clono_filt_opt_def: ClonoFiltOptDefault, // default filtering options for clonotypes - pub clono_filt_opt: ClonoFiltOpt, // filtering options for clonotypes - pub clono_print_opt: ClonoPrintOpt, // printing options for clonotypes - pub clono_group_opt: ClonoGroupOpt, // grouping options for clonotypes - pub parseable_opt: ParseableOpt, // parseable output options - pub pathlist: Vec, // list of input files - pub last_modified: Vec, // last modified for pathlist + pub clono_filt_opt: ClonoFiltOpt, // filtering options for clonotypes + pub clono_print_opt: ClonoPrintOpt, // printing options for clonotypes + pub clono_group_opt: ClonoGroupOpt, // grouping options for clonotypes + pub parseable_opt: ParseableOpt, // parseable output options + pub pathlist: Vec, // list of input files + pub last_modified: Vec, // last modified for pathlist } pub static mut WALLCLOCK: f64 = 0.0; diff --git a/enclone_core/src/lib.rs b/enclone_core/src/lib.rs index 6a8485250..bf914f99f 100644 --- a/enclone_core/src/lib.rs +++ b/enclone_core/src/lib.rs @@ -107,7 +107,6 @@ pub fn expand_integer_ranges(x: &str) -> String { } lazy_static! { - pub static ref BUG_REPORT_ADDRESS: Mutex> = Mutex::new(Vec::::new()); pub static ref REMOTE_HOST: Mutex> = Mutex::new(Vec::::new()); } diff --git a/enclone_vars/Cargo.toml b/enclone_vars/Cargo.toml index 556021135..713a4daf1 100644 --- a/enclone_vars/Cargo.toml +++ b/enclone_vars/Cargo.toml @@ -23,6 +23,6 @@ exclude = ["src/bin/var_test.rs", "src/vars"] [dependencies] io_utils = { path = "../io_utils" } itertools.workspace = true -pretty_trace = { path = "../pretty_trace" } + string_utils = { path = "../string_utils" } vector_utils = { path = "../vector_utils" } diff --git a/enclone_vars/src/bin/export_code.rs b/enclone_vars/src/bin/export_code.rs index 2837fde90..533dcee60 100644 --- a/enclone_vars/src/bin/export_code.rs +++ b/enclone_vars/src/bin/export_code.rs @@ -6,12 +6,10 @@ use enclone_vars::export_code::export_code; use io_utils::{fwrite, open_for_write_new}; -use pretty_trace::PrettyTrace; use std::io::Write; fn main() { - PrettyTrace::new().on(); let outs = export_code(0); for out in outs { let mut f = open_for_write_new![&out.0]; diff --git a/enclone_vars/src/bin/var_sort.rs b/enclone_vars/src/bin/var_sort.rs index e10b32753..b9516daa1 100644 --- a/enclone_vars/src/bin/var_sort.rs +++ b/enclone_vars/src/bin/var_sort.rs @@ -3,11 +3,10 @@ // Sort and replace the vars file. use enclone_vars::sort_vars; -use pretty_trace::PrettyTrace; + use std::io::Write; fn main() { - PrettyTrace::new().on(); let old = std::fs::read_to_string("enclone_vars/src/vars").unwrap(); let new = sort_vars(&old); if new != old { diff --git a/enclone_vars/src/bin/var_test.rs b/enclone_vars/src/bin/var_test.rs index 9a59fb74f..e20ff7c17 100644 --- a/enclone_vars/src/bin/var_test.rs +++ b/enclone_vars/src/bin/var_test.rs @@ -3,10 +3,8 @@ // Parse the vars file to test if it's valid. use enclone_vars::var::parse_variables; -use pretty_trace::PrettyTrace; fn main() { - PrettyTrace::new().on(); let old = std::fs::read_to_string("enclone_vars/src/vars").unwrap(); let _ = parse_variables(&old); } diff --git a/equiv/src/lib.rs b/equiv/src/lib.rs index fc8648383..1196b78b9 100644 --- a/equiv/src/lib.rs +++ b/equiv/src/lib.rs @@ -176,7 +176,6 @@ impl EquivRel { // there are 1618950 orbits // 1.5 seconds, delta peak mem = 258 Mb // disjoint-sets = "0.4.2" - // extern crate disjoint_sets; use disjoint_sets::UnionFind; let mut uf = UnionFind::::new(N as usize); diff --git a/fasta_tools/README.md b/fasta_tools/README.md deleted file mode 100644 index 4cad8e1d5..000000000 --- a/fasta_tools/README.md +++ /dev/null @@ -1,2 +0,0 @@ -This crate contains utilities that are used by the crate -pretty_trace. In time the contents of this crate may be documented, but for now, we recommend against directly using them, as they may be changed. diff --git a/graph_simple/README.md b/graph_simple/README.md deleted file mode 100644 index 4cad8e1d5..000000000 --- a/graph_simple/README.md +++ /dev/null @@ -1,2 +0,0 @@ -This crate contains utilities that are used by the crate -pretty_trace. In time the contents of this crate may be documented, but for now, we recommend against directly using them, as they may be changed. diff --git a/hyperbase/README.md b/hyperbase/README.md deleted file mode 100644 index 4cad8e1d5..000000000 --- a/hyperbase/README.md +++ /dev/null @@ -1,2 +0,0 @@ -This crate contains utilities that are used by the crate -pretty_trace. In time the contents of this crate may be documented, but for now, we recommend against directly using them, as they may be changed. diff --git a/io_utils/README.md b/io_utils/README.md deleted file mode 100644 index 4cad8e1d5..000000000 --- a/io_utils/README.md +++ /dev/null @@ -1,2 +0,0 @@ -This crate contains utilities that are used by the crate -pretty_trace. In time the contents of this crate may be documented, but for now, we recommend against directly using them, as they may be changed. diff --git a/kmer_lookup/README.md b/kmer_lookup/README.md deleted file mode 100644 index 4cad8e1d5..000000000 --- a/kmer_lookup/README.md +++ /dev/null @@ -1,2 +0,0 @@ -This crate contains utilities that are used by the crate -pretty_trace. In time the contents of this crate may be documented, but for now, we recommend against directly using them, as they may be changed. diff --git a/load_feature_bc/README.md b/load_feature_bc/README.md deleted file mode 100644 index 4cad8e1d5..000000000 --- a/load_feature_bc/README.md +++ /dev/null @@ -1,2 +0,0 @@ -This crate contains utilities that are used by the crate -pretty_trace. In time the contents of this crate may be documented, but for now, we recommend against directly using them, as they may be changed. diff --git a/pretty_trace/.gitignore b/pretty_trace/.gitignore deleted file mode 100644 index eb5a316cb..000000000 --- a/pretty_trace/.gitignore +++ /dev/null @@ -1 +0,0 @@ -target diff --git a/pretty_trace/Cargo.toml b/pretty_trace/Cargo.toml deleted file mode 100644 index afb284b6f..000000000 --- a/pretty_trace/Cargo.toml +++ /dev/null @@ -1,31 +0,0 @@ -[package] -name = "pretty_trace" -# When version is bumped, version in README.md also needs to be bumped. -version = "0.5.24" -authors = ["David Jaffe "] -license = "MIT" -description = "Tools for generating pretty tracebacks and for profiling." -keywords = ["stack", "trace", "traceback", "profiling"] -edition = "2018" -include = ["src/lib.rs", "LICENSE", "README.md"] -repository = "https://github.com/10XGenomics/enclone_ranger" - -[dependencies] -backtrace = "0.3" -io_utils = { path = "../io_utils", optional = true } -lazy_static = "1" -libc = "0.2" -nix = { version = ">=0.19, <0.28", features = ["signal"] } -stats_utils = { path = "../stats_utils", optional = true } -string_utils = { path = "../string_utils" } -tables = { path = "../tables", optional = true } -vector_utils = { path = "../vector_utils" } - -[target.'cfg(not(windows))'.dependencies] -pprof = { version = ">=0.7, <0.14", features = ["prost-codec"], optional = true } - -[features] -pprof = ["dep:pprof", "dep:io_utils", "dep:stats_utils", "dep:tables"] - -[dev-dependencies] -rayon = "1" diff --git a/pretty_trace/LICENSE b/pretty_trace/LICENSE deleted file mode 100644 index 2837d2442..000000000 --- a/pretty_trace/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2018-2019 10x Genomics, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/pretty_trace/README.md b/pretty_trace/README.md deleted file mode 100644 index d2a2c7ff9..000000000 --- a/pretty_trace/README.md +++ /dev/null @@ -1 +0,0 @@ -See pretty_trace for documentation. diff --git a/pretty_trace/examples/bad_traceback.rs b/pretty_trace/examples/bad_traceback.rs deleted file mode 100644 index 4fadd91cd..000000000 --- a/pretty_trace/examples/bad_traceback.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) 2019 10X Genomics, Inc. All rights reserved. - -// When tested under OS X, this code correctly panics, but the resulting -// traceback does not reach the main program. Interestingly, setting -// RUST_FULL_TRACE does not help, but commenting out the PrettyTrace line does. -// -// This was observed under macOS Version 10.13.5, and could conceivably be -// version dependent. - -use pretty_trace::PrettyTrace; -use std::fs; - -fn main() { - PrettyTrace::new().on(); - let not = "file_that_does_not_exist"; - let _ = fs::read_to_string(not).unwrap(); -} diff --git a/pretty_trace/src/lib.rs b/pretty_trace/src/lib.rs deleted file mode 100644 index 1abbca375..000000000 --- a/pretty_trace/src/lib.rs +++ /dev/null @@ -1,1447 +0,0 @@ -// Copyright (c) 2018 10X Genomics, Inc. All rights reserved. - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ -// TOP LEVEL DOCUEMENTATION -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -//! This crate provide tools for generating pretty tracebacks and for profiling. - -//! # Pretty tracebacks -//! -//! Stack traces (or "tracebacks") are a fundamental vehicle for describing -//! what code is doing at a given instant. A beautiful thing about rust -//! is that crashes nearly always yield tracebacks, and those -//! tracebacks nearly always extend all the way from the 'broken' -//! code line all the way to the main program. We may take these properties -//! for granted but in general neither is true for other languages, including C++. -//! -//! However, as in other languages, native rust tracebacks are verbose. A major -//! goal of this crate is to provide succinct and readable "pretty" tracebacks, in -//! place of the native tracebacks. These pretty traces can be -//! ten times shorter than native tracebacks. In -//! addition, unlike rust native tracebacks, pretty traces are obtained without -//! setting an environment variable. -//! -//! # Profiling -//! -//! Profiling is a fundamental tool for optimizing code. -//! Standard profiling tools including perf are powerful, however they -//! can be challenging to use. This crate provides a profiling capability that -//! is completely trivial to invoke and interpret, and yields a -//! tiny file as output. -//! -//! The idea is very simple: if it is possible to significantly speed up your code, -//! this should be directly visible from a modest sample of tracebacks chosen at -//! random. And these tracebacks can be generated for any main program by adding a -//! simple command-line option to it that causes it to enter a special 'profile' -//! mode, gathering tracebacks and then terminating. This uses the pprof -//! crate to gather tracebacks. -//! -//! For example this command-line option might be -//! PROFILE to turn on profiling. It's your choice how to specify -//! this command-line option, but this crate makes it trivial to do so. -//! With a few minutes' work, -//! you can make it possible to profile your code with essentially zero work, -//! whenever you like. See the functions start_profiling and -//! stop_profiling. Note that to produce useful output, one needs to specify a list -//! of blacklisted crates, such as std. The entries from these crates are removed -//! from the tracebacks. -//! -//! # A brief guide for using pretty trace -//! -//! First make sure that you have rust debug on: it seems to be enough to have -//! debug = 1 set in Cargo.toml for debug and/or release mode, -//! depending on which youre using. -//! -//!
Now to access pretty trace, put this in your Cargo.toml -//!
-//! pretty_trace = { path = "../pretty_trace" }
-//! 
-//! and this -//!
-//! use pretty_trace::*;
-//! 
-//! in your main program. -//! -//!
Next to turn on pretty traces, it is enough to insert this -//!
-//!     PrettyTrace::new().on();
-//! 
-//! at the beginning of your main program. And you're good to go! Any panic -//! will cause a pretty traceback to be generated. -//! -//! Several other useful features are described below. These include the capability -//! of tracing to know where you are in your data (and not just your code), and -//! for focusing profiling on a key set of crates that you're optimizing. -//! -//! # Credit -//! -//! This code was developed at 10x Genomics, and is based in part on C++ code developed at the -//! Whitehead Institute Center for Genome Research / Broad Institute starting in 2000, and -//! included in . -//! -//! # FAQ -//! -//! 1. Could a pretty traceback lose important information? -//!

Possibly. For this reason we provide the capability of dumping a full -//! traceback to a file (as 'insurance') and also an environment variable to -//! force full tracebacks. However we have not seen examples where important -//! information is lost.

-//! 2. Can the pretty traceback itself be saved to a separate file? -//!

Yes this capability is provided.

-//! 3. Can I get a traceback on Ctrl-C? -//!

Yes, if you do this -//!
-//!     PrettyTrace::new().ctrlc().on();
-//! 
-//! then any Ctrl-C will be converted into a panic, and then you'll get a trackback. -//! -//! # Full disclosure -//! -//! ◼ The code has only been confirmed to work under linux. The code has been -//! used under OS X, but tracebacks can be incomplete. An example is provided -//! of this behavior. -//! -//! ◼ Ideally out-of-memory events would be caught and converted to panics so -//! we could trace them, but we don't. This is a general rust problem that no one -//! has figured out how to solve. See issue 43596 and internals 3673. -//! -//! ◼ The code parses the output of a formatted stack trace, rather then -//! generating output directly from a formal stack trace structure (which it -//! should do). This makes it vulnerable to changes in stack trace formatting. -//! -//! ◼ There is an ugly blacklist of strings that is fragile. This may -//! be an intrinsic feature of the approach. -//! -//! ◼ In general, tracebacks in parallel code do not go back to the main program. -//! -//! # More -//! -//! See the documentation for PrettyTrace, linked to below. -//! -//! # To do -//! -//! ◼ Rewrite so that tracebacks are formatted in the same way in all cases, in the fashion -//! carried out by profiling. And reuse the same code. - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ -// EXTERNAL DEPENDENCIES -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -use backtrace::Backtrace; -#[cfg(all(not(target_os = "windows"), feature = "pprof"))] -use io_utils::open_for_write_new; -use lazy_static::lazy_static; -use libc::SIGINT; -#[cfg(all(not(target_os = "windows"), feature = "pprof"))] -use std::fmt::Write as _; - -#[cfg(not(target_os = "windows"))] -use nix::sys::signal::{sigaction, SaFlags, SigAction, SigHandler, SigSet, Signal}; - -#[cfg(not(target_os = "windows"))] -use nix::Error; - -#[cfg(all(not(target_os = "windows"), feature = "pprof"))] -use pprof::protos::Message; - -#[cfg(all(not(target_os = "windows"), feature = "pprof"))] -use pprof::ProfilerGuard; - -#[cfg(all(not(target_os = "windows"), feature = "pprof"))] -use stats_utils::percent_ratio; -use std::{ - collections::HashMap, - env, - fs::File, - io::{BufWriter, Write}, - ops::Deref, - panic, - str::from_utf8, - sync::atomic::AtomicBool, - sync::atomic::Ordering::SeqCst, - sync::{Mutex, RwLock}, - thread, - thread::ThreadId, - time, - time::Instant, -}; - -#[cfg(not(target_os = "windows"))] -use std::os::unix::io::FromRawFd; - -use string_utils::{stringme, strme, TextUtils}; -#[cfg(all(not(target_os = "windows"), feature = "pprof"))] -use tables::print_tabular_vbox; -#[cfg(all(not(target_os = "windows"), feature = "pprof"))] -use vector_utils::make_freq; -use vector_utils::{contains_at, erase_if}; - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ -// PROFILING -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -#[cfg(all(not(target_os = "windows"), feature = "pprof"))] -static mut GUARD: Option> = None; - -#[cfg(all(not(target_os = "windows"), feature = "pprof"))] -static mut REPORT: Option = None; - -#[cfg(all(not(target_os = "windows"), feature = "pprof"))] -static mut BLACKLIST: Vec = Vec::new(); - -/// Start profiling, blacklisting the given crates. -/// -/// Without blacklisting, profiling can be extremely verbose. We recommend blackisting at least -/// `alloc`, `build`, `core`, `rayon`, `rayon-core`, `serde`, `serde-json`, `std` and -/// `unknown`. However what should be blacklisted depends on what you're trying to understand. -/// If you examine the tracebacks generated by profiling, you can tune the list appropriately. -/// -/// It is not clear how the timing of the profiling is handled. There is a parameter `frequency` -/// that is passed to the profiling machinery, but we don't know what it does. -/// -/// Profiling appears to correctly represent wallclock in parallel loops. - -#[cfg(all(not(target_os = "windows"), feature = "pprof"))] -pub fn start_profiling(blacklist: &[String]) { - let frequency = 1000; - unsafe { - BLACKLIST = blacklist.to_vec(); - GUARD = Some(pprof::ProfilerGuard::new(frequency).unwrap()); - } -} - -/// Stop profiling and dump tracebacks. -/// This assumes that you have called start_profiling. -/// The functions stop_profiling and dump_profiling_as_proto can both be run, in either order. - -#[cfg(all(not(target_os = "windows"), feature = "pprof"))] -pub fn stop_profiling() { - unsafe { - if REPORT.is_none() { - let report = GUARD.as_ref().unwrap().report().build(); - if report.is_err() { - panic!("Failed to build profiling report."); - } - REPORT = Some(report.unwrap()); - } - let report = REPORT.as_ref().unwrap(); - let mut traces = Vec::::new(); - let blacklist = &BLACKLIST; - let mut n = 0; - for (frames, count) in report.data.iter() { - let m = &frames.frames; - n += count; - let mut symv = Vec::>::new(); - for mi in m { - for s in mi { - let mut name = s.name(); - if name.ends_with("::{{closure}}") { - name = name.rev_before("::{{closure}}").to_string(); - } - if name.contains("::") { - name = name.rev_after("::").to_string(); - } - let filename = match s.filename.as_ref() { - Some(name) => name.to_str().unwrap(), - _ => "unknown", - }; - let (file, mut version, mut cratex) = - if filename.contains("/cargo/git/checkouts/") { - let post = filename.after("/cargo/git/checkouts/"); - if post.contains("/src/") && post.rev_before("/src/").contains('/') { - let mid = post.rev_before("/src/"); - let file = post.after("/src/"); - if mid.after("/").contains('/') { - (file, mid.between("/", "/"), mid.rev_after("/")) - } else { - let cratex = post.before("/"); - ( - file, - mid.rev_after("/"), - if cratex.contains('-') { - cratex.rev_before("-") - } else { - cratex - }, - ) - } - } else { - ("unknown", "", "unknown") - } - } else if filename.contains("/src/") - && filename.rev_before("/src/").contains('/') - { - ( - filename.rev_after("/src/"), - "", - filename.rev_before("/src/").rev_after("/"), - ) - } else { - ("unknown", "", "unknown") - }; - let lineno = match s.lineno { - Some(n) => format!("{}", n), - _ => "?".to_string(), - }; - if cratex.contains('-') && version.is_empty() { - let c = cratex.rev_before("-"); - let d = cratex.rev_after("-"); - // check to see if d = x.y.z for some nonnegative integers x, y, z - if d.contains('.') - && d.after(".").contains('.') - && d.before(".").parse::().is_ok() - && d.between(".", ".").parse::().is_ok() - && d.rev_after(".").parse::().is_ok() - { - cratex = c; - version = d; - } - } - let blacklisted = blacklist.iter().any(|b| b == cratex); - if !blacklisted && file.ends_with(".rs") { - symv.push(vec![ - name, - cratex.to_string(), - version.to_string(), - file.to_string(), - lineno, - ]); - } - } - } - if !symv.is_empty() { - let mut log = String::new(); - print_tabular_vbox(&mut log, &symv, 0, b"l|l|l|l|l", false, false); - for _ in 0..*count { - let x = log.to_string(); - traces.push(x); - } - } - } - traces.sort(); - let mut freq = Vec::<(u32, String)>::new(); - make_freq(&traces, &mut freq); - let mut report = String::with_capacity(61 + 40 * freq.len()); - let traced = 100.0 * traces.len() as f64 / n as f64; - write!( - report, - "\nPRETTY TRACE PROFILE\n\nTRACED = {:.1}%\n\nTOTAL = {}\n\n", - traced, - traces.len() - ) - .unwrap(); - let mut total = 0; - for (i, x) in freq.iter().enumerate() { - total += x.0 as usize; - write!( - report, - "[{}] COUNT = {} = {:.2}% ⮕ {:.2}%\n{}\n", - i + 1, - x.0, - percent_ratio(x.0 as usize, traces.len()), - percent_ratio(total, traces.len()), - x.1 - ) - .unwrap(); - } - print!("{}", report); - }; -} - -/// Call this to dump a proto file containing the profiling information. -/// This assumes that you have called start_profiling. -/// The functions stop_profiling and dump_profiling_as_proto can both be run, in either order. - -#[cfg(all(not(target_os = "windows"), feature = "pprof"))] -pub fn dump_profiling_as_proto(f: &str) { - unsafe { - if REPORT.is_none() { - let report = GUARD.as_ref().unwrap().report().build(); - REPORT = Some(report.expect("Failed to build profiling report.")); - } - let report = REPORT.as_ref().unwrap(); - let profile = report.pprof().unwrap(); - let mut y = Vec::new(); - profile.encode(&mut y).unwrap(); - let mut out = open_for_write_new![&f]; - out.write_all(&y).unwrap(); - } -} - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ -// PRETTY TRACE STRUCTURE -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -/// A `PrettyTrace` is the working structure for this crate. See also the top-level -/// crate documentation. - -#[derive(Default)] -pub struct PrettyTrace { - // filename to dump full traceback to upon panic - pub full_file: Option, - // file descriptor to dump second copy of traceback to upon panic - pub fd: Option, - // exit message - pub exit_message: Option, - // thread message - pub message: Option<&'static CHashMap>, - // is profile mode on? - pub profile: bool, - // count for profile mode - pub count: Option, - // separation in seconds for profile mode - pub sep: f32, - // whitelist for profile mode - pub whitelist: Option>, - // convert Ctrl-Cs to panics - pub ctrlc: bool, - pub ctrlc_debug: bool, - pub noexit: bool, - pub function_to_run: Option ()>, -} - -/// Normal usage of `PrettyTrace` is to call -///
-/// PrettyTrace::new().< set some things >.on();
-/// 
-/// once near the begining of your main program. The 'things' are all the -/// functions shown below other than new and on. - -impl PrettyTrace { - /// Initialize a PrettyTrace object. This does nothing - /// in and of itself. - - pub fn new() -> PrettyTrace { - PrettyTrace::default() - } - - /// Cause a PrettyTrace object to do something: change the - /// behavior of response to panic! to produce a prettified - /// traceback and perform profiling, if profile() has been called. - /// Calling of on is mandatory. It must be called exactly once - /// at the end of a chain of operations on a PrettyTrace object. - /// But this is not enforced. - - pub fn on(&mut self) { - let fd = if self.fd.is_some() { - self.fd.unwrap() - } else { - -1_i32 - }; - let mut haps = Happening::new(); - if self.profile { - if self.whitelist.is_none() { - self.whitelist = Some(Vec::::new()); - } - haps.initialize( - &self.whitelist.clone().unwrap(), - self.count.unwrap(), - self.sep, - ); - } - let full_file = if self.full_file.is_some() { - self.full_file.clone().unwrap() - } else { - String::new() - }; - if self.message.is_some() { - force_pretty_trace_fancy( - full_file, - fd, - self.exit_message.clone(), - self.message.unwrap(), - &haps, - self.ctrlc, - self.ctrlc_debug, - self.noexit, - self.function_to_run, - ); - } else { - let tm = new_thread_message(); - force_pretty_trace_fancy( - full_file, - fd, - self.exit_message.clone(), - tm, - &haps, - self.ctrlc, - self.ctrlc_debug, - self.noexit, - self.function_to_run, - ); - } - } - - /// Cause a Ctrl-C interrupt to be turned into a panic, and thence - /// produce a traceback for the main thread. This does not allow you to see - /// what other threads are doing. If you Ctrl-C twice in rapid - /// succession, you may elide the traceback, but this is unreliable. Occasionally single - /// interrupts are also incorrectly handled. - - pub fn ctrlc(&mut self) -> &mut PrettyTrace { - self.ctrlc = true; - self - } - - /// Same as ctrlc, but generates some debugging information. For development - /// purposes. - - pub fn ctrlc_debug(&mut self) -> &mut PrettyTrace { - self.ctrlc = true; - self.ctrlc_debug = true; - self - } - - /// Turn off call to std::process::exit(101), which is normally triggered after - /// printing a traceback (on panic). This could be useful if you want to run a bunch of - /// tests, some of which fail, but you want to see the outcome of all of them. Note that - /// 101 is the standard exit status for rust panics. - /// - /// The downside of noexit is that you may get multiple tracebacks if your - /// code fails in a parallel loop. - - pub fn noexit(&mut self) -> &mut PrettyTrace { - self.noexit = true; - self - } - - /// After print a traceback, pass the traceback contents to the given function. For example, - /// this could be used to send a bug report. - - pub fn run_this(&mut self, f: fn(&str) -> ()) -> &mut PrettyTrace { - self.function_to_run = Some(f); - self - } - - /// Define a file, that in the event that a traceback is triggered by a - /// panic, will be used to dump a full traceback to. The - /// raison d'etre for this is that an abbreviated pretty traceback might - /// in some cases elide useful information (although this has not been observed). - /// - /// This may only be set from the main thread of a process. We disallow setting it from - /// other threads because `PrettyTrace` works by setting the panic hook, which is global, - /// and a value for `full_file` set by one thread might not be valid for another. - /// - /// You can also force PrettyTrace to emit full tracebacks by - /// setting the environment variable RUST_FULL_TRACE. - - pub fn full_file(&mut self, full_file: &str) -> &mut PrettyTrace { - self.full_file = Some(full_file.to_string()); - if thread::current().name().unwrap() != "main" { - panic!( - "PrettyTrace::full_file was called from a non-main thread. This is not\n\ - allowed because PrettyTrace works by setting the panic hook, which is global.\n\ - A value set by one thread might not be valid for another." - ); - } - self - } - - /// Define a file descriptor, that in the event a traceback is triggered by a - /// panic, will be used to dump a second copy of the traceback to. - - pub fn fd(&mut self, fd: i32) -> &mut PrettyTrace { - self.fd = Some(fd); - self - } - - /// Define a message that is to be omitted after a traceback and before exiting. - - /// # Example - ///
-    /// fn main() {
-    ///     let message = "Dang it, you found a bug!  Please call us at (999) 123-4567.";
-    ///     PrettyTrace::new().exit_message(&message).on();
-
-    pub fn exit_message(&mut self, message: &str) -> &mut PrettyTrace {
-        self.exit_message = Some(message.to_string());
-        self
-    }
-
-    /// Define a message object that will be used by threads to store their status.
-    /// This is printed if a traceback is triggered by a panic, and where
-    /// code is traversing data in a loop, can be used to determine not only where
-    /// execution is in the code, but also where it is in the data.
-    ///
-    /// This may only be set from the main thread of a process.  We disallow setting it from
-    /// other threads because `PrettyTrace` works by setting the panic hook, which is global,
-    /// and a value for `message` set by one thread might not be valid for another.
-
-    /// # Example
-    /// 
-    /// use std::thread;
-    /// fn main() {
-    ///     let message = new_thread_message();
-    ///     PrettyTrace::new().message(&message).on();
-    ///     ...
-    ///     // do this whenever thread status changes enough to care
-    ///     message.insert( thread::current().id(), "here is what I'm doing now" );
-    ///     ...
-    /// }
-    /// 
- - pub fn message(&mut self, message: &'static CHashMap) -> &mut PrettyTrace { - self.message = Some(message); - if thread::current().name().unwrap() != "main" { - panic!( - "PrettyTrace::message was called from a non-main thread. This is not\n\ - allowed because PrettyTrace works by setting the panic hook, which is global.\n\ - A value set by one thread might not be valid for another." - ); - } - self - } -} - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ -// HAPPENING STRUCTURE -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -// Data structure for control of happening handling. This could probably be -// elided now. - -struct Happening { - pub on: bool, // turned on? - pub whitelist: Vec, // tracebacks are grepped for these - pub hcount: usize, // number of tracebacks to gather - pub sep: f32, // separation in seconds -} - -impl Happening { - pub fn new() -> Happening { - Happening { - on: false, - whitelist: Vec::::new(), - hcount: 0, - sep: 1.0, - } - } - - // EXAMPLE: set whitelist to a or b or c, hcount to 250, sep to 1.0 - // let mut happening = Happening::new(); - // happening.initialize( &vec![ "a", "b", "c" ], 250, 1.0 ); - - pub fn initialize(&mut self, whitelist: &[String], hcount: usize, sep: f32) { - self.on = true; - self.whitelist = whitelist.to_owned(); - self.hcount = hcount; - self.sep = sep; - } -} - -static CTRLC_DEBUG: AtomicBool = AtomicBool::new(false); - -lazy_static! { - static ref HAPPENING: Mutex = Mutex::new(Happening::new()); -} - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ -// SIGNAL HANDLING -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -// Redirect SIGINT and SIGUSR1 interrupts to the function "handler". - -#[cfg(not(target_os = "windows"))] -fn install_signal_handler(happening: bool, ctrlc: bool) -> Result<(), Error> { - if happening { - let handler = SigHandler::Handler(handler); - let action = SigAction::new(handler, SaFlags::SA_RESTART, SigSet::empty()); - unsafe { - sigaction(Signal::SIGUSR1, &action)?; - } - } - if ctrlc { - let handler = SigHandler::Handler(handler); - let action = SigAction::new(handler, SaFlags::SA_RESTART, SigSet::empty()); - unsafe { - sigaction(Signal::SIGINT, &action)?; - } - } - Ok(()) -} - -static mut HEARD_CTRLC: usize = 0; - -extern "C" fn handler(sig: i32) { - let sep = HAPPENING.lock().unwrap().sep; - let sleep_time = (sep * 1000.0).round() as u64; - if sig == SIGINT { - if CTRLC_DEBUG.load(SeqCst) { - unsafe { - eprint!("\ncaught Ctrl-C"); - eprintln!(" #{}", HEARD_CTRLC + 1); - } - } - unsafe { - if HEARD_CTRLC > 0 { - HEARD_CTRLC += 1; - std::process::exit(0); - } - HEARD_CTRLC += 1; - thread::sleep(time::Duration::from_millis(sleep_time)); - if CTRLC_DEBUG.load(SeqCst) { - eprintln!("done sleeping"); - } - if HEARD_CTRLC > 1 { - std::process::exit(0); - } - } - eprintln!(); - panic!( - "Ctrl-C (SIGINT) interrupt detected\n\nThe traceback below only \ - shows the master thread. If your code includes\n\ - multithreading, you may need to turn that off to obtain \ - a meaningful traceback." - ); - } -} - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ -// CORE TRACEBACK FUNCTION -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -/// Super simplifed concurrent HashMap for use with pretty_trace. The only public method is -/// `insert`, allowing the user to set the current thread message. -pub struct CHashMap { - map: RwLock>, -} - -impl CHashMap -where - K: std::hash::Hash + std::cmp::Eq, -{ - pub fn new() -> CHashMap { - CHashMap { - map: RwLock::new(HashMap::new()), - } - } - - pub fn insert(&self, k: K, v: V) { - self.map.write().unwrap().insert(k, v); - } -} - -impl Default for CHashMap -where - K: std::hash::Hash + std::cmp::Eq, -{ - fn default() -> Self { - Self::new() - } -} - -/// See PrettyTrace documentation for how this is used. - -pub fn new_thread_message() -> &'static CHashMap { - let hashmap = CHashMap::new(); - let box_thread_message = Box::new(hashmap); - let thread_message: &'static CHashMap = Box::leak(box_thread_message); - thread_message -} - -static TRACING: AtomicBool = AtomicBool::new(false); - -/// See PrettyTrace documentation for how this is used. - -fn force_pretty_trace_fancy( - log_file_name: String, - fd: i32, - exit_message: Option, - thread_message: &'static CHashMap, - happening: &Happening, - ctrlc: bool, - ctrlc_debug: bool, - noexit: bool, - function_to_run: Option ()>, -) { - // Set up to catch SIGNINT and SIGUSR1 interrupts. - - #[cfg(not(target_os = "windows"))] - { - let _ = install_signal_handler(happening.on, ctrlc); - } - if ctrlc_debug { - CTRLC_DEBUG.store(true, SeqCst); - } - - // Get time so we can report time used. - - let t = Instant::now(); - - // Set up panic hook. If we panic, this code gets run. - - let _ = panic::take_hook(); - panic::set_hook(Box::new(move |info| { - // Prevent multiple threads from issuing tracebacks. - - if TRACING.load(SeqCst) { - return; - } - TRACING.store(true, SeqCst); - - // Get backtrace. - - let backtrace = Backtrace::new(); - - // Get thread message. - - let mut tm = String::new(); - let this_thread = thread::current().id(); - let tmx = thread_message.map.read(); - if tmx.is_err() { - eprintln!("\nProblem processing thread message in PrettyTrace.\n"); - std::process::exit(1); - } - if tmx.as_ref().unwrap().contains_key(&this_thread) { - tm = format!("{}\n\n", tmx.unwrap().get(&this_thread).unwrap().deref()); - } - - // Handle verbose mode. - - let mut _verbose = false; - for (key, _value) in env::vars() { - if key == "RUST_FULL_TRACE" { - let bt: Vec = format!("{backtrace:?}").into_bytes(); - let thread = thread::current(); - let thread = thread.name().unwrap_or("unnamed"); - let msg = match info.payload().downcast_ref::<&'static str>() { - Some(s) => *s, - None => match info.payload().downcast_ref::() { - Some(s) => &**s, - None => "Box", - }, - }; - let msg2 = match info.location() { - Some(location) => format!( - "thread '{}' panicked at {}:{}", - thread, - location.file(), - location.line() - ), - None => format!("thread '{thread}' panicked "), - }; - eprintln!( - "\nRUST PROGRAM PANIC\n\n(Full traceback. \ - Rerun with env var RUST_FULL_TRACE unset to \ - see short traceback.)\n\n{}{}\n\n{}\n\n{}\n", - tm, - &msg, - &msg2, - from_utf8(&bt).unwrap() - ); - std::process::exit(101); - } - } - - // Prettify the traceback. - - let bt: Vec = format!("{backtrace:?}").into_bytes(); - let all_out = prettify_traceback(&bt, &Vec::::new(), false); - - // Print thread panic message. Bail before doing so if broken pipe - // detected. This protects against running e.g. "exec |& head -50" - // (if exec is the name of the executable), which can otherwise bomb - // out asserting "illegal instruction". - // - // Actually, not printing the thread identifier, because this is rarely - // of interest. And you can get the full traceback if you want it. - - let msg = match info.payload().downcast_ref::<&'static str>() { - Some(s) => *s, - None => match info.payload().downcast_ref::() { - Some(s) => &**s, - None => "Box", - }, - }; - let mut em = String::new(); - if exit_message.is_some() { - em = format!("{}\n\n", exit_message.as_ref().unwrap()); - } - let msg = match info.location() { - Some(location) => { - let loc = location.file(); - - // Replace long constructs of the form /rustc/......./src/ - // by /rustc//src/. - - let mut x2 = loc.to_owned(); - let x2_orig = x2.clone(); - if loc.contains("/rustc/") && loc.after("/rustc/").contains("/src/") { - let y = loc.between("/rustc/", "/src/"); - if y.len() > 10 { - x2 = x2.replace(y, ""); - } - } - if loc.contains("/checkouts/") && loc.after("/checkouts/").contains("/src/") { - let y = loc.between("/checkouts/", "/src/"); - if y.len() > 10 { - x2 = x2.replace(y, ""); - } - } - - // Format lead message. - - let pre = format!("{}:{}", x2, location.line()); - let prex = if all_out.contains(&pre) || x2_orig.contains("pretty_trace") { - "".to_string() - } else { - format!("\n\n0: ◼ {pre}") - }; - let long_msg = if log_file_name.is_empty() { - "Rerun with env var RUST_FULL_TRACE set to see full traceback.".to_string() - } else { - format!("Full traceback is at {log_file_name}.") - }; - format!( - "RUST PROGRAM PANIC AFTER {} SECONDS\n\n(Shortened traceback. \ - {})\n\n{}{}{}", - t.elapsed().as_secs(), - long_msg, - tm, - msg, - prex - ) - } - None => format!("RUST PROGRAM PANIC\n\n{msg}"), - }; - if msg.contains("Broken pipe") { - std::process::exit(101); - } - - // Now print stuff. Package as a single print line to prevent - // interweaving if multiple threads panic. Also check for read permission on the - // executable. Not having that would likely result in a truncated traceback. - - let mut out = format!("\n{}\n\n", &msg); - let ex = std::env::current_exe(); - match ex { - Err(_) => { - out += "█ WARNING. It was not possible to get the path of your executable.\n\ - █ This may result in a defective traceback.\n\n"; - } - Ok(ex) => { - let ex = ex.to_str(); - match ex { - None => { - out += - "█ WARNING. The path of your executable could not be converted into\n\ - █ a string. This is weird and might result in a defective traceback.\n\n"; - } - Some(ex) => { - let f = File::open(ex); - if f.is_err() { - out += - "█ WARNING. Your executable file could not be opened for reading.\n\ - █ This might be because it does not have read permission set for you.\n\ - █ This may result in a defective traceback.\n\n"; - } - } - }; - } - }; - out += &all_out; - out += &em; - eprint!("{out}"); - - // Dump traceback to file descriptor. - - let mut failed = false; - #[cfg(not(target_os = "windows"))] - { - if fd >= 0 { - unsafe { - let mut err_file = File::from_raw_fd(fd); - let x = err_file.write(out.as_bytes()); - if x.is_err() { - eprintln!("\nProblem in PrettyTrace writing to file descriptor {fd}.\n"); - failed = true; - } - } - } - } - - // Dump full traceback to log file. - - if !log_file_name.is_empty() { - let f = File::create(&log_file_name); - if f.is_err() { - eprintln!( - "\nDuring panic, attempt to create full log file \ - named {log_file_name} failed, giving up.\n" - ); - std::process::exit(101); - } - let mut log_file_writer = BufWriter::new(f.unwrap()); - let bt: Vec = format!("{backtrace:?}").into_bytes(); - let thread = thread::current(); - let thread = thread.name().unwrap_or("unnamed"); - let msg = match info.payload().downcast_ref::<&'static str>() { - Some(s) => *s, - None => match info.payload().downcast_ref::() { - Some(s) => &**s, - None => "Box", - }, - }; - let msg = match info.location() { - Some(location) => format!( - "thread '{}' panicked at '{}': {}:{}", - thread, - msg, - location.file(), - location.line() - ), - None => format!("thread '{thread}' panicked at '{msg}'"), - }; - log_file_writer - .write_fmt(format_args!( - "\nRUST PROGRAM PANIC\n\n(Full traceback.)\n\n{}{}\n\n{}\n{}", - tm, - &msg, - from_utf8(&bt).unwrap(), - em - )) - .unwrap(); - } - - // Run function. - - if let Some(function_to_run) = function_to_run { - function_to_run(&out); - } - - // Exit. Turning this off would seem to have no effect, but this is not the case - // in general. If your code fails in a parallel loop, without the exit, you may - // be flooded with tracebacks, one per thread. - - if !noexit || failed { - std::process::exit(101); - } - })); -} - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ -// PRETTIFY TRACEBACK -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -#[allow(clippy::cognitive_complexity)] -fn prettify_traceback(bt: &[u8], whitelist: &[String], pack: bool) -> String { - // Parse the backtrace into lines. - - let mut btlines = Vec::>::new(); - let mut line = Vec::::new(); - for z in bt { - if *z == b'\n' { - // Replace long constructs of the form /rustc/......./src/ - // by /rustc//src/. - // and some similar things. - - let x = stringme(&line); - let mut x2 = x.clone(); - if x.contains("/rustc/") && x.after("/rustc/").contains("/src/") { - let y = x.between("/rustc/", "/src/"); - if y.len() > 10 { - x2 = x2.replace(y, ""); - } - } - if x.contains("/checkouts/") && x.after("/checkouts/").contains("/src/") { - let y = x.between("/checkouts/", "/src/"); - if y.len() > 10 { - x2 = x2.replace(y, ""); - } - } - let srcgit = "/src/github.com-"; - if x.contains(srcgit) && x.after(srcgit).contains('/') { - let y = x.between(srcgit, "/"); - if y.len() > 10 { - x2 = x2.replace(&format!("{srcgit}{y}"), "/"); - } - } - if x2.contains("/src/") && x2.before("/src/").contains('/') && x2.contains(' ') { - x2 = format!( - "{} {}/src/{}", - x2.rev_before(" "), - x2.before("/src/").rev_after("/"), - x2.after("/src/") - ); - } - btlines.push(x2.as_bytes().to_vec()); - - // Reset line. - - line.clear(); - } else { - line.push(*z); - } - } - - // Convert the traceback into a Vec>>>. The outer vector corresponds to the - // traceback block. Within each block is a vector of traceback entries, and each entry is - // itself a vector of on or two lines. It is two, except when there is no code line number. - // The initial blanks and block numbers are stripped off. - - let mut blocks = Vec::>>>::new(); - let mut block = Vec::>>::new(); - let mut blocklet = Vec::>::new(); - for x in btlines { - // Ignore blank lines. - - if x.is_empty() { - continue; - } - - // Determine if this line begins a block, i.e. looks like :<...>. - - let mut s = x.as_slice(); - let mut j = 0; - while j < s.len() { - if s[j] != b' ' { - break; - } - j += 1; - } - while j < s.len() { - if !(s[j] as char).is_ascii_digit() { - break; - } - j += 1; - } - if j < s.len() && s[j] == b':' && !block.is_empty() { - if !blocklet.is_empty() { - block.push(blocklet.clone()); - blocklet.clear(); - } - blocks.push(block.clone()); - block.clear(); - s = &s[j + 1..s.len()]; - } - - // Proceed. - - let mut j = 0; - while j < s.len() { - if s[j] != b' ' { - break; - } - j += 1; - } - s = &s[j..s.len()]; - blocklet.push(s.to_vec()); - if s.starts_with(b"at ") { - block.push(blocklet.clone()); - blocklet.clear(); - } - } - if !blocklet.is_empty() { - block.push(blocklet.clone()); - } - if !block.is_empty() { - blocks.push(block.clone()); - } - - // Define the blacklist. - - let blacklist = vec![ - "pretty_trace", - "::libunwind::", - "::Backtrace::", - "::backtrace::", - "::panicking::", - "::lang_start", - "rust_maybe_catch_panic", - "rust_panic", - "libc_start_main", - "::force_pretty_trace::", - "::thread::", - "- rayon", - "rayon::iter", - "rayon_core::", - "- start_thread", - "", // turning this on yields cleaner tracebacks but loses critical information - "/panic.rs", - "/panicking.rs", - "catch_unwind", - "lang_start_internal", - "libstd/rt.rs", - "tokio", - "future", - "tonic::server", - "hyper::proto", - ]; - - // Remove certain 'unwanted' blocklets. - - for x in blocks.iter_mut() { - let mut to_delete = vec![false; x.len()]; - 'block: for j in 0..x.len() { - // Ugly exemption to make a test work. - - for k in 0..x[j].len() { - let s = strme(&x[j][k]); - if s.contains("pretty_trace::tests") { - continue 'block; - } - } - - // Otherwise blocklet may not contain a blacklisted string. - - 'outer1: for k in 0..x[j].len() { - let s = strme(&x[j][k]); - for b in blacklist.iter() { - if s.contains(b) { - to_delete[j] = true; - break 'outer1; - } - } - } - - // Blocklet must contain a whitelisted string (if whitelist provided). - - if !to_delete[j] && !whitelist.is_empty() { - let mut good = false; - 'outer2: for k in 0..x[j].len() { - let s = strme(&x[j][k]); - for b in whitelist.iter() { - if s.contains(b) { - good = true; - break 'outer2; - } - } - } - if !good { - to_delete[j] = true; - } - } - - // Don't allow blockets of length one that end with "- main". - - let s = strme(&x[j][0]); - if !to_delete[j] && x[j].len() == 1 && s.ends_with("- main") { - to_delete[j] = true; - } - - // Don't allow blocklets whose first line has the form ... main(...). - - let m = " main ("; - if s.contains(m) && s.after(m).contains(')') && !s.between(m, ")").contains('(') { - to_delete[j] = true; - } - } - erase_if(x, &to_delete); - } - - // Remove any block having length zero. - - let mut to_delete = vec![false; blocks.len()]; - for i in 0..blocks.len() { - if blocks[i].is_empty() { - to_delete[i] = true; - } - } - erase_if(&mut blocks, &to_delete); - - // stuff from earlier version, not addressing now - - // !s2.contains(".rs:0") - // ((!s.contains(" - <") && !s.contains("rayon::iter")) || k == i) - - // if s.contains("::{{closure}}") { - // s = s.rev_before("::{{closure}}"); - // } - - // Contract paths that look like " .../.../src/...". - - let src = b"/src/".to_vec(); - for z in blocks.iter_mut() { - for w in z.iter_mut() { - if w.len() == 2 { - let mut x = Vec::::new(); - let y = w[1].clone(); - 'outer: for j in 0..y.len() { - if contains_at(&y, &src, j) { - for k in (0..j).rev() { - if y[k] != b'/' { - continue; - } - for l in (0..k).rev() { - if y[l] == b' ' { - for u in y.iter().take(l + 1) { - x.push(*u); - } - for u in y.iter().skip(k + 1) { - x.push(*u); - } - break 'outer; - } - } - } - } - } - if !x.is_empty() { - w[1] = y; - } - } - } - } - - // Emit prettified output. - - let mut all_out = String::new(); - for (i, x) in blocks.iter().enumerate() { - let num = format!("{}: ", i + 1); - let sub = stringme(vec![b' '; num.len()].as_slice()); - for (j, y) in x.iter().enumerate() { - for (k, z) in y.iter().enumerate() { - if j == 0 && k == 0 { - all_out += # - } else { - all_out += ⊂ - } - if k > 0 { - all_out += "◼ "; - } - let mut s = stringme(z); - if k == 0 && s.contains("::") { - let cc = s.rfind("::").unwrap(); - s.truncate(cc); - } - if s.ends_with("::{{closure}}") { - s = s.rev_before("::{{closure}}").to_string(); - } - all_out += &s; - all_out += "\n"; - } - } - if !pack { - all_out += "\n"; - } - } - all_out -} - -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ -// TESTS -// ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ - -#[cfg(test)] -mod tests { - - #[inline(never)] - fn looper(results: &mut Vec<(usize, usize)>) { - use rayon::prelude::*; - results.par_iter_mut().for_each(|r| { - for _ in 0..10_000 { - r.1 = r.1.wrapping_add(1).wrapping_add(r.0 * r.1); - } - }); - } - - use super::*; - - #[test] - fn test_ctrlc() { - use libc::{kill, SIGINT}; - use nix::unistd::{fork, pipe, ForkResult}; - use std::fs::File; - use std::io::{Read, Write}; - use std::os::unix::io::FromRawFd; - use std::{thread, time}; - use string_utils::strme; - - // Create a pipe. - - let pipefd = pipe().unwrap(); - - // Set up tracebacks with ctrlc and using the pipe. The use of the exit message - // makes absolutely no sense at all. However, without it, something very weird - // happens in the test. The test seems to finish and return control, and then you - // get a message "thread panicked while processing panic. aborting.". So this is - // a weird workaround for a problem that is not understood. And the problem arose - // exactly when the exit message was added, with this commit: - // - // commit d32162f15d7192eeb077744bace91a3cb27094b0 - // Author: David Jaffe - // Date: Thu Dec 19 03:04:12 2019 -0800 - // add exit_message(...) to PrettyTrace - // - // In addition, and connected to this, - // cargo test - // does not work, and instead you need to use - // cargo test -- --nocapture - - let message = "Dang it, you found a bug! Please call us at (999) 123-4567."; - PrettyTrace::new() - .exit_message(message) - .ctrlc() - .fd(pipefd.1) - .on(); - // PrettyTrace::new().ctrlc().fd(pipefd.1).on(); - - // Create stuff needed for computation we're going to interrupt. - - let mut results = vec![(1_usize, 0_usize); 100_000_000]; - - // State what we're doing. - - let bar = "▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓"; - println!("\n{bar}"); - println!("DELIBERATELY PROVOKING A PANIC USING A CTRL-C"); - print!("{bar}"); - std::io::stdout().flush().unwrap(); - - // Fork, and inside the fork, give separate execution paths for parent and child. - - unsafe { - match fork() { - // PARENT: - Ok(ForkResult::Parent { child: _, .. }) => { - // Sleep to let the child finish, then read enough bytes from pipe - // so that we get the traceback. - - thread::sleep(time::Duration::from_millis(2000)); - let mut buffer = [0; 2000]; - let mut err_file = File::from_raw_fd(pipefd.0); - let _ = err_file.read(&mut buffer).unwrap(); - - // Evaluate the traceback. We check only whether the traceback - // points to the inner loop. - - println!("{bar}"); - println!("TESTING THE PANIC FOR CORRECTNESS"); - println!("{bar}"); - let s = strme(&buffer); - let have_main = s.split_terminator('\n').any(|line| - // Test relaxed here because on an AWS box, we did not see the ::looper part. - // if lines[i].contains("pretty_trace::tests::looper") { - line.contains("pretty_trace::tests")); - if have_main { - println!("\ngood: found inner loop\n"); - } else { - panic!("FAIL: DID NOT FIND INNER LOOP"); - } - } - - // CHILD: - Ok(ForkResult::Child) => { - // Spawn a thread to kill the child. - - thread::spawn(|| { - thread::sleep(time::Duration::from_millis(100)); - let pid = std::process::id() as i32; - kill(pid, SIGINT); - }); - - // Do the actual work that the ctrl-c is going to interrupt. - - looper(&mut results); - } - Err(_) => println!("Fork failed"), - } - } - } -} diff --git a/stats_utils/README.md b/stats_utils/README.md deleted file mode 100644 index 4cad8e1d5..000000000 --- a/stats_utils/README.md +++ /dev/null @@ -1,2 +0,0 @@ -This crate contains utilities that are used by the crate -pretty_trace. In time the contents of this crate may be documented, but for now, we recommend against directly using them, as they may be changed. diff --git a/stirling_numbers/src/lib.rs b/stirling_numbers/src/lib.rs index f71fc3938..7b3e16210 100644 --- a/stirling_numbers/src/lib.rs +++ b/stirling_numbers/src/lib.rs @@ -8,22 +8,6 @@ //! //! This crate consists of a few functions related to these Stirling numbers. -#[cfg(not(debug_assertions))] -#[cfg(test)] -extern crate num_bigint; -#[cfg(not(debug_assertions))] -#[cfg(test)] -extern crate num_rational; -#[cfg(not(debug_assertions))] -#[cfg(test)] -extern crate rand; -#[cfg(not(debug_assertions))] -#[cfg(test)] -extern crate rayon; -#[cfg(not(debug_assertions))] -#[cfg(test)] -extern crate vector_utils; - use num_traits::{Num, One, Zero}; use std::ops::MulAssign; diff --git a/string_utils/README.md b/string_utils/README.md deleted file mode 100644 index 4cad8e1d5..000000000 --- a/string_utils/README.md +++ /dev/null @@ -1,2 +0,0 @@ -This crate contains utilities that are used by the crate -pretty_trace. In time the contents of this crate may be documented, but for now, we recommend against directly using them, as they may be changed. diff --git a/tables/README.md b/tables/README.md deleted file mode 100644 index 4cad8e1d5..000000000 --- a/tables/README.md +++ /dev/null @@ -1,2 +0,0 @@ -This crate contains utilities that are used by the crate -pretty_trace. In time the contents of this crate may be documented, but for now, we recommend against directly using them, as they may be changed. diff --git a/vdj_ann_ref/Cargo.toml b/vdj_ann_ref/Cargo.toml index 90d904002..627263d16 100644 --- a/vdj_ann_ref/Cargo.toml +++ b/vdj_ann_ref/Cargo.toml @@ -17,7 +17,7 @@ fasta_tools = { version = "0.1", path = "../fasta_tools" } flate2 = "1" io_utils = { path = "../io_utils" } perf_stats = { path = "../perf_stats" } -pretty_trace = { path = "../pretty_trace" } + sha2 = ">=0.9.3, <0.11" string_utils = { path = "../string_utils" } vector_utils = { path = "../vector_utils" } diff --git a/vdj_ann_ref/src/bin/build_supp_ref.rs b/vdj_ann_ref/src/bin/build_supp_ref.rs index 8b44b4e70..ca3ec431d 100644 --- a/vdj_ann_ref/src/bin/build_supp_ref.rs +++ b/vdj_ann_ref/src/bin/build_supp_ref.rs @@ -25,7 +25,6 @@ // // And these also need to go into the references on /mnt/opt and possibly /mnt/test. -// extern crate vdj_asm_utils; // use vdj_asm_utils::*; use debruijn::{ @@ -34,7 +33,7 @@ use debruijn::{ }; use exons::fetch_exons; use fasta_tools::read_fasta_into_vec_dna_string_plus_headers; -use pretty_trace::PrettyTrace; + use std::{collections::HashMap, env}; use string_utils::TextUtils; @@ -45,8 +44,6 @@ fn print_fasta(header: &str, seq: &DnaStringSlice) { fn main() { // Force panic to yield a traceback, and make it a pretty one. - PrettyTrace::new().on(); - // Parse arguments. let args: Vec = env::args().collect(); diff --git a/vdj_ann_ref/src/bin/build_vdj_ref.rs b/vdj_ann_ref/src/bin/build_vdj_ref.rs index 5c4c1758d..6325df119 100644 --- a/vdj_ann_ref/src/bin/build_vdj_ref.rs +++ b/vdj_ann_ref/src/bin/build_vdj_ref.rs @@ -85,7 +85,7 @@ use debruijn::{ use fasta_tools::load_genbank_accession; use flate2::read::MultiGzDecoder; use perf_stats::elapsed; -use pretty_trace::PrettyTrace; + use process::Command; use sha2::{Digest, Sha256}; use std::io::copy; @@ -378,8 +378,6 @@ fn main() { // Force panic to yield a traceback, and make it a pretty one. - PrettyTrace::new().on(); - // Parse arguments. let args: Vec = env::args().collect(); diff --git a/vdj_ann_ref/src/bin/build_vdj_ref_exons.rs b/vdj_ann_ref/src/bin/build_vdj_ref_exons.rs index 6d50d6d75..7b24f62b9 100644 --- a/vdj_ann_ref/src/bin/build_vdj_ref_exons.rs +++ b/vdj_ann_ref/src/bin/build_vdj_ref_exons.rs @@ -13,7 +13,7 @@ use debruijn::dna_string::DnaString; use flate2::read::MultiGzDecoder; -use pretty_trace::PrettyTrace; + use process::Command; use sha2::{Digest, Sha256}; use std::io::copy; @@ -177,8 +177,6 @@ fn parse_gtf_file(gtf: &str, demangle: &HashMap, exons: &mut Vec fn main() { // Force panic to yield a traceback, and make it a pretty one. - PrettyTrace::new().on(); - // Parse arguments. let args: Vec = env::args().collect(); diff --git a/vector_utils/README.md b/vector_utils/README.md deleted file mode 100644 index 4cad8e1d5..000000000 --- a/vector_utils/README.md +++ /dev/null @@ -1,2 +0,0 @@ -This crate contains utilities that are used by the crate -pretty_trace. In time the contents of this crate may be documented, but for now, we recommend against directly using them, as they may be changed.