-
-
Notifications
You must be signed in to change notification settings - Fork 102
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
97f9e9a
commit a3aba3b
Showing
14 changed files
with
197 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
use std::future::Future; | ||
use std::sync::Arc; | ||
use std::thread; | ||
|
||
use crossbeam::channel::{unbounded, Sender}; | ||
use futures::{executor, FutureExt}; | ||
use lightproc::prelude::*; | ||
use std::sync::atomic::AtomicUsize; | ||
use lazy_static::lazy_static; | ||
use std::panic::AssertUnwindSafe; | ||
use lightproc::proc_ext::ProcFutureExt; | ||
use lightproc::recoverable_handle::RecoverableHandle; | ||
|
||
|
||
fn spawn_on_thread<F, R>(future: F) -> RecoverableHandle<R> | ||
where | ||
F: Future<Output = R> + Send + 'static, | ||
R: Send + 'static, | ||
{ | ||
lazy_static! { | ||
// A channel that holds scheduled tasks. | ||
static ref QUEUE: Sender<LightProc> = { | ||
let (sender, receiver) = unbounded::<LightProc>(); | ||
|
||
// Start the executor thread. | ||
thread::spawn(move || { | ||
for proc in receiver { | ||
proc.run(); | ||
} | ||
}); | ||
|
||
sender | ||
}; | ||
} | ||
|
||
let schedule = |t| QUEUE.send(t).unwrap(); | ||
let (proc, handle) = LightProc::recoverable( | ||
future, | ||
schedule, | ||
ProcStack { | ||
pid: AtomicUsize::new(1), | ||
after_complete: Some(Arc::new(|| { | ||
println!("After complete"); | ||
})), | ||
before_start: Some(Arc::new(|| { | ||
println!("Before start"); | ||
})), | ||
after_panic: Some(Arc::new(|| { | ||
println!("After panic"); | ||
})) | ||
}, | ||
); | ||
|
||
proc.schedule(); | ||
|
||
handle | ||
} | ||
|
||
fn main() { | ||
let handle = spawn_on_thread(async { | ||
panic!("Panic here!"); | ||
}); | ||
|
||
executor::block_on(handle); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,6 +35,7 @@ where | |
before_start: Some(Arc::new(|| { | ||
println!("Before start"); | ||
})), | ||
after_panic: None | ||
}, | ||
); | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
use std::future::Future; | ||
use std::panic::{UnwindSafe, catch_unwind, AssertUnwindSafe}; | ||
use pin_utils::unsafe_pinned; | ||
use std::any::Any; | ||
use std::task::{Context, Poll}; | ||
use std::pin::Pin; | ||
|
||
#[derive(Debug)] | ||
#[must_use = "futures do nothing unless you `.await` or poll them"] | ||
pub struct CatchUnwind<Fut> where Fut: Future { | ||
future: Fut, | ||
} | ||
|
||
impl<Fut> CatchUnwind<Fut> where Fut: Future + UnwindSafe { | ||
unsafe_pinned!(future: Fut); | ||
|
||
pub(super) fn new(future: Fut) -> CatchUnwind<Fut> { | ||
CatchUnwind { future } | ||
} | ||
} | ||
|
||
impl<Fut> Future for CatchUnwind<Fut> | ||
where Fut: Future + UnwindSafe, | ||
{ | ||
type Output = Result<Fut::Output, Box<dyn Any + Send>>; | ||
|
||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { | ||
catch_unwind(AssertUnwindSafe(|| self.future().poll(cx)))?.map(Ok) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
use std::mem; | ||
|
||
#[inline] | ||
pub(crate) fn abort_on_panic<T>(f: impl FnOnce() -> T) -> T { | ||
struct Bomb; | ||
|
||
impl Drop for Bomb { | ||
fn drop(&mut self) { | ||
std::process::abort(); | ||
} | ||
} | ||
|
||
let bomb = Bomb; | ||
let t = f(); | ||
mem::forget(bomb); | ||
t | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
use std::future::Future; | ||
use std::panic::UnwindSafe; | ||
use crate::catch_unwind::CatchUnwind; | ||
|
||
pub trait ProcFutureExt: Future { | ||
fn catch_unwind(self) -> CatchUnwind<Self> | ||
where Self: Sized + UnwindSafe | ||
{ | ||
CatchUnwind::new(self) | ||
} | ||
} | ||
|
||
impl<T: ?Sized> ProcFutureExt for T where T: Future {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
use crate::proc_handle::ProcHandle; | ||
use std::thread; | ||
use std::future::Future; | ||
use std::task::{Context, Poll}; | ||
use std::pin::Pin; | ||
use std::panic::resume_unwind; | ||
|
||
pub struct RecoverableHandle<R>(pub ProcHandle<thread::Result<R>>); | ||
|
||
impl<R> Future for RecoverableHandle<R> { | ||
type Output = Option<R>; | ||
|
||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { | ||
match Pin::new(&mut self.0).poll(cx) { | ||
Poll::Pending => Poll::Pending, | ||
Poll::Ready(None) => Poll::Ready(None), | ||
Poll::Ready(Some(Ok(val))) => Poll::Ready(Some(val)), | ||
Poll::Ready(Some(Err(err))) => { | ||
if let Some(after_panic_cb) = self.0.stack().after_panic.clone() { | ||
(*after_panic_cb.clone())(); | ||
} | ||
|
||
resume_unwind(err) | ||
}, | ||
} | ||
} | ||
} |