Skip to content

Commit d3c91e1

Browse files
committed
fix bug where join_timeout would kill the subprocess on first timeout
since join_timeout does no longer consume the handle, killing it on timeout is not appropriate. instead move that to a drop impl also add test for new join_timeout behavior
1 parent 227ac02 commit d3c91e1

File tree

3 files changed

+35
-9
lines changed

3 files changed

+35
-9
lines changed

src/pool.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,7 @@ impl<T: Serialize + DeserializeOwned> PooledHandle<T> {
6262
match self.waiter_rx.recv_timeout(timeout) {
6363
Ok(Ok(rv)) => Ok(rv),
6464
Ok(Err(err)) => Err(err),
65-
Err(mpsc::RecvTimeoutError::Timeout) => {
66-
self.kill().ok();
67-
Err(SpawnError::new_timeout())
68-
}
65+
Err(mpsc::RecvTimeoutError::Timeout) => Err(SpawnError::new_timeout()),
6966
Err(mpsc::RecvTimeoutError::Disconnected) => Err(SpawnError::new_remote_close()),
7067
}
7168
}

src/proc.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -515,11 +515,15 @@ impl<T: Serialize + DeserializeOwned> JoinHandle<T> {
515515
/// Wait for the child process to return a result.
516516
///
517517
/// If the join handle was created from a pool the join is virtualized.
518-
pub fn join(self) -> Result<T, SpawnError> {
519-
match self.inner {
520-
Ok(JoinHandleInner::Process(mut handle)) => handle.join(),
521-
Ok(JoinHandleInner::Pooled(mut handle)) => handle.join(),
522-
Err(err) => Err(err),
518+
pub fn join(mut self) -> Result<T, SpawnError> {
519+
match &mut self.inner {
520+
Ok(JoinHandleInner::Process(ref mut handle)) => handle.join(),
521+
Ok(JoinHandleInner::Pooled(ref mut handle)) => handle.join(),
522+
Err(err) => {
523+
let mut rv_err = SpawnError::new_consumed();
524+
mem::swap(&mut rv_err, err);
525+
Err(rv_err)
526+
}
523527
}
524528
}
525529

@@ -551,6 +555,12 @@ impl<T: Serialize + DeserializeOwned> JoinHandle<T> {
551555
}
552556
}
553557

558+
impl<T> Drop for JoinHandle<T> {
559+
fn drop(&mut self) {
560+
self.kill().ok();
561+
}
562+
}
563+
554564
/// Spawn a new process to run a function with some payload.
555565
///
556566
/// ```rust,no_run

tests/test_pool.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,22 @@ fn test_timeout() {
7777
let val = handle.join_timeout(Duration::from_secs(2)).unwrap();
7878
assert_eq!(val, 42);
7979
}
80+
81+
#[test]
82+
fn test_timeout_twice() {
83+
let pool = Pool::new(2).unwrap();
84+
85+
let mut handle = pool.spawn((), |()| {
86+
thread::sleep(Duration::from_secs(5));
87+
42
88+
});
89+
90+
let err = handle.join_timeout(Duration::from_millis(100)).unwrap_err();
91+
assert!(err.is_timeout());
92+
93+
let err = handle.join_timeout(Duration::from_millis(100)).unwrap_err();
94+
assert!(err.is_timeout());
95+
96+
let val = handle.join_timeout(Duration::from_secs(6)).unwrap();
97+
assert_eq!(val, 42);
98+
}

0 commit comments

Comments
 (0)