< 返回版块

jmjoy 发表于 2019-11-29 23:26

Tags:async,sleep,async-std

代码如下:

use async_std::task;
use futures_util::future::FutureExt;
use std::time::Duration;

async fn test_sleep() {
    async {
        task::sleep(Duration::from_secs(10)).await;
    }.catch_unwind().await;
}

报错:

error[E0277]: the type `std::cell::UnsafeCell<std::option::Option<std::task::Waker>>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
   --> src/mq.rs:240:11
    |
240 |         }.catch_unwind().await;
    |           ^^^^^^^^^^^^ `std::cell::UnsafeCell<std::option::Option<std::task::Waker>>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    |
    = help: within `futures_timer::arc_list::Node<futures_timer::timer::ScheduledTimer>`, the trait `std::panic::RefUnwindSafe` is not implemented for `std::cell::UnsafeCell<std::option::Option<std::task::Waker>>`
    = note: required because it appears within the type `futures_timer::atomic_waker::AtomicWaker`
    = note: required because it appears within the type `futures_timer::timer::ScheduledTimer`
    = note: required because it appears within the type `futures_timer::arc_list::Node<futures_timer::timer::ScheduledTimer>`
    = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `std::sync::Arc<futures_timer::arc_list::Node<futures_timer::timer::ScheduledTimer>>`
    = note: required because it appears within the type `std::option::Option<std::sync::Arc<futures_timer::arc_list::Node<futures_timer::timer::ScheduledTimer>>>`
    = note: required because it appears within the type `futures_timer::delay::Delay`
    = note: required because it appears within the type `{std::time::Duration, impl std::future::Future, fn(std::time::Duration) -> futures_timer::delay::Delay {futures_timer::delay::Delay::new}, std::time::Duration, futures_timer::delay::Delay, impl std::future::Future, async_std::io::timeout::Timeout<impl std::future::Future, ()>, async_std::io::timeout::Timeout<impl std::future::Future, ()>, ()}`
    = note: required because it appears within the type `[static generator@DefId(31:2423 ~ async_std[3304]::io[0]::timeout[0]::timeout[0]::{{closure}}[0]) 0:std::time::Duration, 1:impl std::future::Future {std::time::Duration, impl std::future::Future, fn(std::time::Duration) -> futures_timer::delay::Delay {futures_timer::delay::Delay::new}, std::time::Duration, futures_timer::delay::Delay, impl std::future::Future, async_std::io::timeout::Timeout<impl std::future::Future, ()>, async_std::io::timeout::Timeout<impl std::future::Future, ()>, ()}]`
    = note: required because it appears within the type `std::future::GenFuture<[static generator@DefId(31:2423 ~ async_std[3304]::io[0]::timeout[0]::timeout[0]::{{closure}}[0]) 0:std::time::Duration, 1:impl std::future::Future {std::time::Duration, impl std::future::Future, fn(std::time::Duration) -> futures_timer::delay::Delay {futures_timer::delay::Delay::new}, std::time::Duration, futures_timer::delay::Delay, impl std::future::Future, async_std::io::timeout::Timeout<impl std::future::Future, ()>, async_std::io::timeout::Timeout<impl std::future::Future, ()>, ()}]>`
    = note: required because it appears within the type `impl std::future::Future`
    = note: required because it appears within the type `impl std::future::Future`
    = note: required because it appears within the type `{std::time::Duration, fn(std::time::Duration, impl std::future::Future) -> impl std::future::Future {async_std::io::timeout::timeout::<impl std::future::Future, ()>}, std::time::Duration, fn() -> impl std::future::Future {async_std::future::pending::pending::<std::result::Result<(), std::io::Error>>}, impl std::future::Future, impl std::future::Future, impl std::future::Future, ()}`
    = note: required because it appears within the type `[static generator@DefId(31:4330 ~ async_std[3304]::task[0]::sleep[0]::sleep[0]::{{closure}}[0]) 0:std::time::Duration {std::time::Duration, fn(std::time::Duration, impl std::future::Future) -> impl std::future::Future {async_std::io::timeout::timeout::<impl std::future::Future, ()>}, std::time::Duration, fn() -> impl std::future::Future {async_std::future::pending::pending::<std::result::Result<(), std::io::Error>>}, impl std::future::Future, impl std::future::Future, impl std::future::Future, ()}]`
    = note: required because it appears within the type `std::future::GenFuture<[static generator@DefId(31:4330 ~ async_std[3304]::task[0]::sleep[0]::sleep[0]::{{closure}}[0]) 0:std::time::Duration {std::time::Duration, fn(std::time::Duration, impl std::future::Future) -> impl std::future::Future {async_std::io::timeout::timeout::<impl std::future::Future, ()>}, std::time::Duration, fn() -> impl std::future::Future {async_std::future::pending::pending::<std::result::Result<(), std::io::Error>>}, impl std::future::Future, impl std::future::Future, impl std::future::Future, ()}]>`
    = note: required because it appears within the type `impl std::future::Future`
    = note: required because it appears within the type `impl std::future::Future`
    = note: required because it appears within the type `{fn(std::time::Duration) -> impl std::future::Future {async_std::task::sleep::sleep}, fn(u64) -> std::time::Duration {std::time::Duration::from_secs}, u64, std::time::Duration, impl std::future::Future, impl std::future::Future, ()}`
    = note: required because it appears within the type `[static generator@src/mq.rs:238:15: 240:10 {fn(std::time::Duration) -> impl std::future::Future {async_std::task::sleep::sleep}, fn(u64) -> std::time::Duration {std::time::Duration::from_secs}, u64, std::time::Duration, impl std::future::Future, impl std::future::Future, ()}]`
    = note: required because it appears within the type `std::future::GenFuture<[static generator@src/mq.rs:238:15: 240:10 {fn(std::time::Duration) -> impl std::future::Future {async_std::task::sleep::sleep}, fn(u64) -> std::time::Duration {std::time::Duration::from_secs}, u64, std::time::Duration, impl std::future::Future, impl std::future::Future, ()}]>`
    = note: required because it appears within the type `impl std::future::Future`

error[E0277]: the type `(dyn std::error::Error + std::marker::Send + std::marker::Sync + 'static)` may not be safely transferred across an unwind boundary
   --> src/mq.rs:240:11
    |
240 |         }.catch_unwind().await;
    |           ^^^^^^^^^^^^ `(dyn std::error::Error + std::marker::Send + std::marker::Sync + 'static)` may not be safely transferred across an unwind boundary
    |
    = help: the trait `std::panic::UnwindSafe` is not implemented for `(dyn std::error::Error + std::marker::Send + std::marker::Sync + 'static)`
    = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `std::ptr::Unique<(dyn std::error::Error + std::marker::Send + std::marker::Sync + 'static)>`
    = note: required because it appears within the type `std::boxed::Box<(dyn std::error::Error + std::marker::Send + std::marker::Sync + 'static)>`
    = note: required because it appears within the type `std::io::error::Custom`
    = note: required because of the requirements on the impl of `std::panic::UnwindSafe` for `std::ptr::Unique<std::io::error::Custom>`
    = note: required because it appears within the type `std::boxed::Box<std::io::error::Custom>`
    = note: required because it appears within the type `std::io::error::Repr`
    = note: required because it appears within the type `std::io::Error`
    = note: required because it appears within the type `std::result::Result<(), std::io::Error>`
    = note: required because it appears within the type `std::marker::PhantomData<std::result::Result<(), std::io::Error>>`
    = note: required because it appears within the type `async_std::future::pending::Pending<std::result::Result<(), std::io::Error>>`
    = note: required because it appears within the type `{async_std::future::pending::Pending<std::result::Result<(), std::io::Error>>, async_std::future::pending::Pending<std::result::Result<(), std::io::Error>>, async_std::future::pending::Pending<std::result::Result<(), std::io::Error>>, ()}`
    = note: required because it appears within the type `[static generator@DefId(31:65 ~ async_std[3304]::future[0]::pending[0]::pending[0]::{{closure}}[0]) {async_std::future::pending::Pending<std::result::Result<(), std::io::Error>>, async_std::future::pending::Pending<std::result::Result<(), std::io::Error>>, async_std::future::pending::Pending<std::result::Result<(), std::io::Error>>, ()}]`
    = note: required because it appears within the type `std::future::GenFuture<[static generator@DefId(31:65 ~ async_std[3304]::future[0]::pending[0]::pending[0]::{{closure}}[0]) {async_std::future::pending::Pending<std::result::Result<(), std::io::Error>>, async_std::future::pending::Pending<std::result::Result<(), std::io::Error>>, async_std::future::pending::Pending<std::result::Result<(), std::io::Error>>, ()}]>`
    = note: required because it appears within the type `impl std::future::Future`
    = note: required because it appears within the type `impl std::future::Future`
    = note: required because it appears within the type `{std::time::Duration, fn(std::time::Duration, impl std::future::Future) -> impl std::future::Future {async_std::io::timeout::timeout::<impl std::future::Future, ()>}, std::time::Duration, fn() -> impl std::future::Future {async_std::future::pending::pending::<std::result::Result<(), std::io::Error>>}, impl std::future::Future, impl std::future::Future, impl std::future::Future, ()}`
    = note: required because it appears within the type `[static generator@DefId(31:4330 ~ async_std[3304]::task[0]::sleep[0]::sleep[0]::{{closure}}[0]) 0:std::time::Duration {std::time::Duration, fn(std::time::Duration, impl std::future::Future) -> impl std::future::Future {async_std::io::timeout::timeout::<impl std::future::Future, ()>}, std::time::Duration, fn() -> impl std::future::Future {async_std::future::pending::pending::<std::result::Result<(), std::io::Error>>}, impl std::future::Future, impl std::future::Future, impl std::future::Future, ()}]`
    = note: required because it appears within the type `std::future::GenFuture<[static generator@DefId(31:4330 ~ async_std[3304]::task[0]::sleep[0]::sleep[0]::{{closure}}[0]) 0:std::time::Duration {std::time::Duration, fn(std::time::Duration, impl std::future::Future) -> impl std::future::Future {async_std::io::timeout::timeout::<impl std::future::Future, ()>}, std::time::Duration, fn() -> impl std::future::Future {async_std::future::pending::pending::<std::result::Result<(), std::io::Error>>}, impl std::future::Future, impl std::future::Future, impl std::future::Future, ()}]>`
    = note: required because it appears within the type `impl std::future::Future`
    = note: required because it appears within the type `impl std::future::Future`
    = note: required because it appears within the type `{fn(std::time::Duration) -> impl std::future::Future {async_std::task::sleep::sleep}, fn(u64) -> std::time::Duration {std::time::Duration::from_secs}, u64, std::time::Duration, impl std::future::Future, impl std::future::Future, ()}`
    = note: required because it appears within the type `[static generator@src/mq.rs:238:15: 240:10 {fn(std::time::Duration) -> impl std::future::Future {async_std::task::sleep::sleep}, fn(u64) -> std::time::Duration {std::time::Duration::from_secs}, u64, std::time::Duration, impl std::future::Future, impl std::future::Future, ()}]`
    = note: required because it appears within the type `std::future::GenFuture<[static generator@src/mq.rs:238:15: 240:10 {fn(std::time::Duration) -> impl std::future::Future {async_std::task::sleep::sleep}, fn(u64) -> std::time::Duration {std::time::Duration::from_secs}, u64, std::time::Duration, impl std::future::Future, impl std::future::Future, ()}]>`
    = note: required because it appears within the type `impl std::future::Future`

评论区

写评论
作者 jmjoy 2019-11-30 10:52

谢谢大佬! 对以下内容的回复:

rsphing 2019-11-30 00:49

FutureExt::catch_unwind 的定义如下:

fn catch_unwind(self) -> CatchUnwind<Self> 
where
    Self: UnwindSafe, 

Self需要实现std::panic::UnwindSafe Trait, 用标准库的std::panic::AssertUnwindSafe 包裹一下就可以了,如下:

async fn test_sleep() {
	let _ = std::panic::AssertUnwindSafe(async {
        task::sleep(Duration::from_secs(10)).await
	}).catch_unwind().await;
}
1 共 2 条评论, 1 页