48 lines
1.0 KiB
Rust
48 lines
1.0 KiB
Rust
use nix::errno::Errno;
|
|
use nix::sys::wait::{waitid, Id, WaitPidFlag, WaitStatus};
|
|
use nix::unistd::Pid;
|
|
|
|
pub struct DebugTarget<S: DebugState> {
|
|
state: S,
|
|
}
|
|
|
|
pub trait DebugState {
|
|
#[allow(dead_code)]
|
|
fn pid(&self) -> Pid;
|
|
}
|
|
|
|
pub struct Stopped {
|
|
pid: Pid,
|
|
}
|
|
|
|
impl DebugState for Stopped {
|
|
fn pid(&self) -> Pid { self.pid }
|
|
}
|
|
|
|
impl DebugTarget<Stopped> {
|
|
pub fn new(pid: Pid) -> Result<Self, Errno> {
|
|
waitid(Id::Pid(pid), WaitPidFlag::WSTOPPED).and(Ok(DebugTarget { state: Stopped { pid } }))
|
|
}
|
|
|
|
pub fn cont(self) -> Result<DebugTarget<Running>, Errno> {
|
|
nix::sys::ptrace::cont(self.state.pid, None).and(Ok(DebugTarget { state: Running { pid: self.state.pid } }))
|
|
}
|
|
}
|
|
|
|
pub struct Running {
|
|
pid: Pid,
|
|
}
|
|
|
|
impl DebugState for Running {
|
|
fn pid(&self) -> Pid { self.pid }
|
|
}
|
|
|
|
|
|
impl DebugTarget<Running> {
|
|
pub fn wait_for_exit(self) -> Result<i32, Errno> {
|
|
waitid(Id::Pid(self.state.pid), WaitPidFlag::WEXITED).and_then(|status| match status {
|
|
WaitStatus::Exited(_, exit_code) => Ok(exit_code),
|
|
_ => Err(Errno::EINVAL), // TODO: custom error type?
|
|
})
|
|
}
|
|
} |