Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What happens to an async task when it is aborted?

Rust has async methods that can be tied to Abortable futures. The documentation says that, when aborted:

the future will complete immediately without making any further progress.

Will the variables owned by the task bound to the future be dropped? If those variables implement drop, will drop be called? If the future has spawned other futures, will all of them be aborted in a chain?

E.g.: In the following snippet, I don't see the destructor happening for the aborted task, but I don't know if it is not called or happens in a separate thread where the print is not shown.

use futures::executor::block_on;
use futures::future::{AbortHandle, Abortable};

struct S {
    i: i32,
}

impl Drop for S {
    fn drop(&mut self) {
        println!("dropping S");
    }
}

async fn f() -> i32 {
    let s = S { i: 42 };
    std::thread::sleep(std::time::Duration::from_secs(2));
    s.i
}

fn main() {
    println!("first test...");
    let (abort_handle, abort_registration) = AbortHandle::new_pair();
    let _ = Abortable::new(f(), abort_registration);
    abort_handle.abort();
    std::thread::sleep(std::time::Duration::from_secs(1));

    println!("second test...");
    let (_, abort_registration) = AbortHandle::new_pair();
    let task = Abortable::new(f(), abort_registration);
    block_on(task).unwrap();
    std::thread::sleep(std::time::Duration::from_secs(1));
}

playground

like image 281
Kahler Avatar asked Jan 06 '20 14:01

Kahler


People also ask

How to cancel async function?

The idea is to pass a CancellationToken to every async function, then wrap every promise in AsyncCheckpoint . So that when the token is cancelled, your async function will be cancelled in the next checkpoint. This idea came from tc39/proposal-cancelable-promises and conradreuter/cancellationtoken.

How to stop async function c#?

You can cancel an asynchronous operation after a period of time by using the CancellationTokenSource. CancelAfter method if you don't want to wait for the operation to finish.

How to cancel async request javascript?

Looking at the code above you can see that at the beginning, you create a new instance of the AbortController DOM interface (1) and bind its signal property to a variable (2). Then you invoke fetch() and pass signal as one of its options (3). To abort fetching the resource you just call abortController. abort() (4).


Video Answer


1 Answers

Yes, values that have been created will be dropped.

In your first example, the future returned by f is never started, so the S is never created. This means that it cannot be dropped.

In the second example, the value is dropped.

This is more obvious if you both run the future and abort it. Here, I spawn two concurrent futures:

  1. create an S and waits 200ms
  2. wait 100ms and abort future #1
use futures::future::{self, AbortHandle, Abortable};
use std::time::Duration;
use tokio::time;

struct S {
    i: i32,
}

impl S {
    fn new(i: i32) -> Self {
        println!("Creating S {}", i);
        S { i }
    }
}

impl Drop for S {
    fn drop(&mut self) {
        println!("Dropping S {}", self.i);
    }
}

#[tokio::main]
async fn main() {
    let create_s = async {
        let s = S::new(42);
        time::delay_for(Duration::from_millis(200)).await;
        println!("Creating {} done", s.i);
    };
    let (abort_handle, abort_registration) = AbortHandle::new_pair();
    let create_s = Abortable::new(create_s, abort_registration);

    let abort_s = async move {
        time::delay_for(Duration::from_millis(100)).await;
        abort_handle.abort();
    };

    let c = tokio::spawn(create_s);
    let a = tokio::spawn(abort_s);

    let (c, a) = future::join(c, a).await;

    println!("{:?}, {:?}", c, a);
}
Creating S 42
Dropping S 42
Ok(Err(Aborted)), Ok(())

Note that I've switched to Tokio to be able to use time::delay_for, as you should never use blocking operations in an async function.

See also:

  • Why does Future::select choose the future with a longer sleep period first?
  • What is the best approach to encapsulate blocking I/O in future-rs?

If the future has spawned other futures, will all of them be aborted in a chain?

No, when you spawn a future, it is disconnected from where it was spawned.

See also:

  • What is the purpose of async/await in Rust?
like image 88
Shepmaster Avatar answered Nov 12 '22 05:11

Shepmaster