Description
Security audit of PR #3640 identified a resource leak in the no-supervisor branch of SpeculationEngine::new_with_supervisor (and new) in crates/zeph-core/src/agent/speculative/mod.rs.
Actual Behavior
In the supervisor = None branch:
tokio::spawn(sweeper_task) returns a JoinHandle
jh.abort_handle() is called to get an AbortHandle
std::mem::forget(jh) discards the JoinHandle
- The
AbortHandle is immediately dropped without being stored
The TaskHandle stored in self.sweeper does NOT abort the real tokio task on Drop. The sweeper runs until the tokio runtime shuts down.
Impact
Not a memory-safety issue (safe Rust). The sweeper iterates an empty HashMap every 5 seconds (negligible CPU). However, in long-running test contexts or when the SpeculationEngine is dropped before the runtime shuts down, the sweeper task leaks.
Recommended Fix
Replace the dummy TaskHandle approach with Option<tokio::task::JoinHandle<()>> stored in the struct and aborted in Drop:
impl Drop for SpeculationEngine {
fn drop(&mut self) {
if let Some(handle) = self.sweeper.take() {
handle.abort();
}
}
}
Files
crates/zeph-core/src/agent/speculative/mod.rs
Depends on
#3636 (merged in PR #3640)
Description
Security audit of PR #3640 identified a resource leak in the no-supervisor branch of
SpeculationEngine::new_with_supervisor(andnew) incrates/zeph-core/src/agent/speculative/mod.rs.Actual Behavior
In the
supervisor = Nonebranch:tokio::spawn(sweeper_task)returns aJoinHandlejh.abort_handle()is called to get anAbortHandlestd::mem::forget(jh)discards theJoinHandleAbortHandleis immediately dropped without being storedThe
TaskHandlestored inself.sweeperdoes NOT abort the real tokio task onDrop. The sweeper runs until the tokio runtime shuts down.Impact
Not a memory-safety issue (safe Rust). The sweeper iterates an empty
HashMapevery 5 seconds (negligible CPU). However, in long-running test contexts or when theSpeculationEngineis dropped before the runtime shuts down, the sweeper task leaks.Recommended Fix
Replace the dummy
TaskHandleapproach withOption<tokio::task::JoinHandle<()>>stored in the struct and aborted inDrop:Files
crates/zeph-core/src/agent/speculative/mod.rsDepends on
#3636 (merged in PR #3640)