Skip to content

Commit

Permalink
move is_recovering_from_trap to futures and re-export in lib.rs
Browse files Browse the repository at this point in the history
  • Loading branch information
lwshang committed Jan 14, 2025
1 parent 0c2b7d0 commit 673f84d
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 1 deletion.
4 changes: 4 additions & 0 deletions ic-cdk/src/api/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -995,6 +995,10 @@ where
/// provides a convenient wrapper for this. In a destructor, `is_recovering_from_trap` serves the same purpose as
/// [std::thread::panicking] - it tells you whether the destructor is executing *because* of a trap,
/// as opposed to just because the scope was exited, so you could e.g. implement mutex poisoning.
#[deprecated(
since = "0.18.0",
note = "Please use `ic_cdk::is_recovering_from_trap` instead."
)]
pub fn is_recovering_from_trap() -> bool {
crate::futures::CLEANUP.load(Ordering::Relaxed)
}
18 changes: 17 additions & 1 deletion ic-cdk/src/futures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::cell::{Cell, RefCell};
use std::future::Future;
use std::pin::Pin;
use std::rc::Rc;
use std::sync::atomic::AtomicBool;
use std::sync::atomic::{AtomicBool, Ordering};
use std::task::Context;

use self::waker::WakerState;
Expand All @@ -28,6 +28,22 @@ pub fn spawn<F: 'static + Future<Output = ()>>(future: F) {

pub(crate) static CLEANUP: AtomicBool = AtomicBool::new(false);

/// Tells you whether the current async fn is being canceled due to a trap/panic.
///
/// If a function traps/panics, then the canister state is rewound to the beginning of the function.
/// However, due to the way async works, the beginning of the function as the IC understands it is actually
/// the most recent `await` from an inter-canister-call. This means that part of the function will have executed,
/// and part of it won't.
///
/// When this happens the CDK will cancel the task, causing destructors to be run. If you need any functions to be run
/// no matter what happens, they should happen in a destructor; the [`scopeguard`](https://docs.rs/scopeguard) crate
/// provides a convenient wrapper for this. In a destructor, `is_recovering_from_trap` serves the same purpose as
/// [std::thread::panicking] - it tells you whether the destructor is executing *because* of a trap,
/// as opposed to just because the scope was exited, so you could e.g. implement mutex poisoning.
pub fn is_recovering_from_trap() -> bool {
crate::futures::CLEANUP.load(Ordering::Relaxed)
}

// This module contains the implementation of a waker we're using for waking
// top-level futures (the ones returned by canister methods). Rc handles the
// heap management for us. Hence, it will be deallocated once we exit the scope and
Expand Down
2 changes: 2 additions & 0 deletions ic-cdk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ pub use api::{
#[doc(inline)]
pub use macros::*;

pub use futures::is_recovering_from_trap;

static DONE: AtomicBool = AtomicBool::new(false);

/// Setup the stdlib hooks.
Expand Down

0 comments on commit 673f84d

Please sign in to comment.