From 5ca024ab8fc17c25b93ec0c4c9b4eac64758fcde Mon Sep 17 00:00:00 2001 From: Jason Foral Date: Fri, 3 Jan 2025 19:06:28 -0500 Subject: [PATCH] Consolidate state related to the timeout watchdog into a single struct field. (Using presence of an `Option` instead of manually synchronizing a boolean). --- .../src/analysis/ddsa_lib/runtime.rs | 66 ++++++++----------- 1 file changed, 28 insertions(+), 38 deletions(-) diff --git a/crates/static-analysis-kernel/src/analysis/ddsa_lib/runtime.rs b/crates/static-analysis-kernel/src/analysis/ddsa_lib/runtime.rs index 6ed2c036..6ad90bda 100644 --- a/crates/static-analysis-kernel/src/analysis/ddsa_lib/runtime.rs +++ b/crates/static-analysis-kernel/src/analysis/ddsa_lib/runtime.rs @@ -35,7 +35,7 @@ pub struct JsRuntime { /// Each `JsRuntime` spawns a thread that lives for as long as the `JsRuntime`, and it is used /// to manually terminate JavaScript executions that go on for too long. Synchronization between /// the `JsRuntime` and this thread is performed through this `watchdog_pair`. - watchdog_pair: Arc<(Mutex, Condvar)>, + watchdog_pair: Arc<(Mutex, Condvar)>, console: Rc>, bridge_context: Rc>, bridge_query_match: QueryMatchBridge, @@ -334,9 +334,7 @@ impl JsRuntime { if let Some(duration) = timeout { let (lock, cvar) = &*self.watchdog_pair; let mut state = lock.lock().unwrap(); - state.timeout_duration = duration; - state.start_time = Instant::now(); - state.is_currently_executing = true; + let _ = state.active_timer.insert((Instant::now(), duration)); drop(state); cvar.notify_one(); } @@ -347,7 +345,7 @@ impl JsRuntime { // and so we don't need to set `is_currently_executing`, nor do we need to (inefficiently) re-notify // via the condvar. We just reset the v8 isolate's termination state and return a timeout error. if tc_ctx_scope.is_execution_terminating() { - debug_assert!(!self.watchdog_pair.0.lock().unwrap().is_currently_executing); + debug_assert!(self.watchdog_pair.0.lock().unwrap().active_timer.is_none()); tc_ctx_scope.cancel_terminate_execution(); tc_ctx_scope.reset(); let timeout = timeout.expect("timeout should exist if we had v8 terminate execution"); @@ -357,7 +355,7 @@ impl JsRuntime { // the watchdog thread to stop actively tracking a timeout. let (lock, cvar) = &*self.watchdog_pair; let mut state = lock.lock().unwrap(); - state.is_currently_executing = false; + state.active_timer = None; drop(state); cvar.notify_one(); } @@ -437,7 +435,7 @@ impl Drop for JsRuntime { let (lock, cvar) = &*self.watchdog_pair; let mut state = lock.lock().unwrap(); // Tell the watchdog thread that it should shut down. - state.watchdog_should_shut_down = true; + state.thread_should_shut_down = true; drop(state); cvar.notify_one(); } @@ -505,8 +503,8 @@ pub(crate) fn inner_make_deno_core_runtime( /// /// The spawned thread may be shut down by setting `should_shut_down` on `JsExecutionState` and /// notifying the thread via the condvar. -fn spawn_watchdog_thread(v8_handle: v8::IsolateHandle) -> Arc<(Mutex, Condvar)> { - let state_pair = Arc::new((Mutex::new(JsExecutionState::new()), Condvar::new())); +fn spawn_watchdog_thread(v8_handle: v8::IsolateHandle) -> Arc<(Mutex, Condvar)> { + let state_pair = Arc::new((Mutex::new(TimeoutState::new()), Condvar::new())); let pair_clone = Arc::clone(&state_pair); std::thread::spawn(move || { @@ -514,25 +512,25 @@ fn spawn_watchdog_thread(v8_handle: v8::IsolateHandle) -> Arc<(Mutex= timeout_threshold { // This branch represents an edge case where the OS couldn't wake this thread up // until after the watchdog should've already triggered a timeout. - - // Trust that v8 will halt execution and eagerly mark the execution as complete so the - // main thread doesn't need to acquire the lock to do it. - state.is_currently_executing = false; + state.active_timer = None; drop(state); v8_handle.terminate_execution(); } else { @@ -540,17 +538,15 @@ fn spawn_watchdog_thread(v8_handle: v8::IsolateHandle) -> Arc<(Mutex, + thread_should_shut_down: bool, } -impl JsExecutionState { +impl TimeoutState { pub fn new() -> Self { Self { - timeout_duration: Duration::default(), - start_time: Instant::now(), - is_currently_executing: false, - watchdog_should_shut_down: false, + active_timer: None, + thread_should_shut_down: false, } } }