(
inner: &Arc<parking_lot::Mutex<ThreadHandleInner>>,
done_event: &Arc<(parking_lot::Mutex<bool>, parking_lot::Condvar)>,
timeout_duration: Option<Duration>,
| 1202 | } |
| 1203 | |
| 1204 | fn join_internal( |
| 1205 | inner: &Arc<parking_lot::Mutex<ThreadHandleInner>>, |
| 1206 | done_event: &Arc<(parking_lot::Mutex<bool>, parking_lot::Condvar)>, |
| 1207 | timeout_duration: Option<Duration>, |
| 1208 | vm: &VirtualMachine, |
| 1209 | ) -> PyResult<()> { |
| 1210 | Self::check_started(inner, vm)?; |
| 1211 | |
| 1212 | let deadline = |
| 1213 | timeout_duration.and_then(|timeout| std::time::Instant::now().checked_add(timeout)); |
| 1214 | |
| 1215 | // Wait for thread completion using Condvar (supports timeout) |
| 1216 | // Loop to handle spurious wakeups |
| 1217 | let (lock, cvar) = &**done_event; |
| 1218 | let mut done = lock.lock(); |
| 1219 | |
| 1220 | // ThreadHandle_join semantics: self-join/finalizing checks |
| 1221 | // apply only while target thread has not reported it is exiting yet. |
| 1222 | if !*done { |
| 1223 | let inner_guard = inner.lock(); |
| 1224 | let current_ident = get_ident(); |
| 1225 | if inner_guard.ident == current_ident |
| 1226 | && inner_guard.state == ThreadHandleState::Running |
| 1227 | { |
| 1228 | return Err(vm.new_runtime_error("Cannot join current thread")); |
| 1229 | } |
| 1230 | if vm |
| 1231 | .state |
| 1232 | .finalizing |
| 1233 | .load(core::sync::atomic::Ordering::Acquire) |
| 1234 | { |
| 1235 | return Err(vm.new_exception_msg( |
| 1236 | vm.ctx.exceptions.python_finalization_error.to_owned(), |
| 1237 | "cannot join thread at interpreter shutdown" |
| 1238 | .to_owned() |
| 1239 | .into(), |
| 1240 | )); |
| 1241 | } |
| 1242 | } |
| 1243 | |
| 1244 | while !*done { |
| 1245 | if let Some(timeout) = timeout_duration { |
| 1246 | let remaining = deadline.map_or(timeout, |deadline| { |
| 1247 | deadline.saturating_duration_since(std::time::Instant::now()) |
| 1248 | }); |
| 1249 | if remaining.is_zero() { |
| 1250 | return Ok(()); |
| 1251 | } |
| 1252 | let result = vm.allow_threads(|| cvar.wait_for(&mut done, remaining)); |
| 1253 | if result.timed_out() && !*done { |
| 1254 | // Timeout occurred and done is still false |
| 1255 | return Ok(()); |
| 1256 | } |
| 1257 | } else { |
| 1258 | // Infinite wait |
| 1259 | vm.allow_threads(|| cvar.wait(&mut done)); |
| 1260 | } |
| 1261 | } |
nothing calls this directly
no test coverage detected