Description
Issue
When using async-std's block_on
, the background tasks spawned are neither stopped neither awaited properly. This means that destructors are not called as they should.
I talk about this with @yoshuawuyts and there seems to be a way to do it with task cancellation but I think async-std should actually stop the tasks gracefully.
Current behavior
To help understand the issue I made this repository to demonstrate: https://github.com/cecton/asyncstd-test-drops
In this example a task is ran in background for async-std and then I use block_on
on a sleep. The sleep finishes before the task actually completes and we exit the block_on
despite things are still running in background.
Right after in the same example I do the exact same thing with tokio and you can see that in tokio the block_on
only exit when the task and its objects are dropped properly.
Here is the output of the program if I comment the tokio example and keep only the async-std example. Note that the destructor is never called:
Running `target/debug/asyncstd-test-drops`
test 1 created
1
2
[Finished running]
The program finished in 2 seconds because the timeout is of 2 seconds. All the blocking tasks in background and objects are just not dropped.
Here is the output of the program if I comment the async-std example and keep only the tokio example. Note that the task is dropped before reaching the marker "2":
Running `target/debug/asyncstd-test-drops`
test 2 created
1
Dropping 2...
Dropped 2.
2
[Finished running]
The program finished in 7 seconds. This is the addition of the 2 blocking codes (std::thread::sleep
). It blocks the thread and prevents tokio to finish.
Now another interesting thing is this: if I keep both examples enabled, this is the output I get:
Running `target/debug/asyncstd-test-drops`
test 1 created
1
2
test 2 created
1
Dropping 2...
test 1 dropped
Dropping 1...
Dropped 2.
2
[Finished running]
The async-std task was still running in background and it finished while the tokio test was running. Here the Test(1)
object created by the async-std task is beginning the drop but it couldn't finish because the tokio drop finished before. I first thought that the background tasks were abruptly killed by async-std but this proves this is not the case. The background tasks are still running, they're just not managed anymore.
Expected behavior
I have worked a lot with asyncio on Python and recently a bit with tokio. I expect that the async runtime will drop things gracefully. You could argue that I could implement a shutdown mechanism (which is true) but that doesn't allow the runtime to simply forget about my objects and not call their destructors.
The best behavior is to wait for the background tasks to get into an awaiting state (waiting for io, waiting for a sleep, etc...) and cancel the task, deleting it and its objects. When everything has been deleted, the block_on
should finish and the program can safely exit.