in sdk/core/azure_core/src/task/standard_spawn.rs [39:78]
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let mut join_state = self.join_state.lock().map_err(|e| {
debug!("Failed to lock join state: {}", e);
Box::new(crate::Error::message(
crate::error::ErrorKind::Other,
format!("Thread panicked: {:?}", e),
)) as Box<dyn std::error::Error + Send>
})?;
// Join handle is present, so we can check if the thread has finished
// and take the handle if it has.
// This is safe because we are holding the lock on the join state.
// We can safely take the handle and join it without blocking.
// This allows us to retrieve the terminal state of the thread.
if join_state.thread_finished {
// Thread is finished, so we can safely take the handle
let Some(join_handle) = join_state.join_handle.take() else {
// The join handle was already removed from the state, we know we're done.
return Poll::Ready(Ok(()));
};
// Since we know the thread is finished, we can safely take the handle
// and join it. This allows us to retrieve the terminal state of the thread.
//
// Technically this might block (because the `thread_finished` flag
// is set before the thread *actually* finishes), but it should be negligible.
match join_handle.join() {
Ok(_) => Poll::Ready(Ok(())),
Err(e) => Poll::Ready(Err(Box::new(crate::Error::message(
crate::error::ErrorKind::Other,
format!("Thread panicked: {:?}", e),
)) as Box<dyn std::error::Error + Send>)),
}
} else {
// Thread is still running, so we need to register the waker
// for when it completes.
join_state.waker = Some(cx.waker().clone());
Poll::Pending
}
}