From fd109382965d6a6fa792347e9c56cce9bbd3d8ae Mon Sep 17 00:00:00 2001 From: Jun Wu Date: Mon, 2 Aug 2021 13:26:26 -0700 Subject: [PATCH] hgcommands: avoid deadlock setting up fail points Summary: FailScenario nested in a single thread can cause deadlock on a Mutex, confirmed by gdb backtrace. Fix that by avoiding nested FailScenario in a single thread. Reviewed By: kulshrax Differential Revision: D30052693 fbshipit-source-id: 8d38b2e40ec30c8024e563f079d2595d76bbae1b --- eden/scm/lib/hgcommands/src/run.rs | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/eden/scm/lib/hgcommands/src/run.rs b/eden/scm/lib/hgcommands/src/run.rs index 37be367785..d44a6529e6 100644 --- a/eden/scm/lib/hgcommands/src/run.rs +++ b/eden/scm/lib/hgcommands/src/run.rs @@ -19,6 +19,7 @@ use hg_http::HgHttpConfig; use once_cell::sync::Lazy; use parking_lot::Mutex; use progress_model::Registry; +use std::cell::Cell; use std::env; use std::fs::File; use std::io; @@ -70,7 +71,7 @@ pub fn run_command(args: Vec, io: &IO) -> i32 { Ok(res) => res, }; - let scenario = FailScenario::setup(); + let scenario = setup_fail_points(); setup_eager_repo(); // This is intended to be "process start". "exec/hgmain" seems to be @@ -171,7 +172,9 @@ pub fn run_command(args: Vec, io: &IO) -> i32 { // so we need to flush now. blackbox::sync(); - scenario.teardown(); + if let Some(scenario) = scenario { + scenario.teardown(); + } exit_code } @@ -568,3 +571,19 @@ fn setup_eager_repo() { *REGISTERED } + +thread_local! { + static FAIL_SETUP: Cell = Cell::new(false); +} + +fn setup_fail_points<'a>() -> Option> { + FAIL_SETUP.with(|b| { + if b.get() { + // Already setup. + None + } else { + b.set(true); + Some(FailScenario::setup()) + } + }) +}