use crate::instance::siginfo_ext::SiginfoExt;
use crate::instance::{FaultDetails, TerminationDetails, YieldedVal};
use crate::sysdeps::UContext;
use libc::{SIGBUS, SIGSEGV};
use std::any::Any;
use std::ffi::{CStr, CString};
pub enum State {
Ready,
Running,
Faulted {
details: FaultDetails,
siginfo: libc::siginfo_t,
context: UContext,
},
Terminating { details: TerminationDetails },
Terminated,
Yielding {
val: YieldedVal,
expecting: Box<dyn Any>,
},
Yielded {
expecting: Box<dyn Any>,
},
Transitioning,
}
impl std::fmt::Display for State {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
State::Ready => write!(f, "ready"),
State::Running => write!(f, "running"),
State::Faulted {
details, siginfo, ..
} => {
write!(f, "{}", details)?;
write!(
f,
" triggered by {}: ",
strsignal_wrapper(siginfo.si_signo)
.into_string()
.expect("strsignal returns valid UTF-8")
)?;
if siginfo.si_signo == SIGSEGV || siginfo.si_signo == SIGBUS {
write!(
f,
" accessed memory at {:p} (inside heap guard)",
siginfo.si_addr_ext()
)?;
}
Ok(())
}
State::Terminated { .. } => write!(f, "terminated"),
State::Terminating { .. } => write!(f, "terminating"),
State::Yielding { .. } => write!(f, "yielding"),
State::Yielded { .. } => write!(f, "yielded"),
State::Transitioning { .. } => {
write!(f, "transitioning (IF YOU SEE THIS, THERE'S PROBABLY A BUG)")
}
}
}
}
impl State {
pub fn is_ready(&self) -> bool {
if let State::Ready { .. } = self {
true
} else {
false
}
}
pub fn is_running(&self) -> bool {
if let State::Running = self {
true
} else {
false
}
}
pub fn is_faulted(&self) -> bool {
if let State::Faulted { .. } = self {
true
} else {
false
}
}
pub fn is_fatal(&self) -> bool {
if let State::Faulted {
details: FaultDetails { fatal, .. },
..
} = self
{
*fatal
} else {
false
}
}
pub fn is_terminated(&self) -> bool {
if let State::Terminated { .. } = self {
true
} else {
false
}
}
pub fn is_yielded(&self) -> bool {
if let State::Yielded { .. } = self {
true
} else {
false
}
}
}
extern "C" {
#[no_mangle]
fn strsignal(sig: libc::c_int) -> *mut libc::c_char;
}
fn strsignal_wrapper(sig: libc::c_int) -> CString {
unsafe { CStr::from_ptr(strsignal(sig)).to_owned() }
}