mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-08-29 00:00:11 +02:00
process: Unix: mark child as reaped on kill
This commit is contained in:
+35
-27
@@ -34,7 +34,6 @@ use mio::unix::{EventedFd, UnixReady};
|
|||||||
use mio::{PollOpt, Ready, Token};
|
use mio::{PollOpt, Ready, Token};
|
||||||
use mio::event::Evented;
|
use mio::event::Evented;
|
||||||
use mio;
|
use mio;
|
||||||
use self::libc::c_int;
|
|
||||||
use self::tokio_signal::unix::Signal;
|
use self::tokio_signal::unix::Signal;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use tokio_io::IoFuture;
|
use tokio_io::IoFuture;
|
||||||
@@ -87,24 +86,21 @@ impl Child {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn kill(&mut self) -> io::Result<()> {
|
pub fn kill(&mut self) -> io::Result<()> {
|
||||||
if self.reaped {
|
if !self.reaped {
|
||||||
Ok(())
|
// NB: SIGKILL cannnot be caught, so the process will definitely exit immediately.
|
||||||
} else {
|
// We're not waiting for the process itself but for the kernel to execute the kill.
|
||||||
self.inner.kill()?;
|
self.inner.kill()?;
|
||||||
let mut status = 0;
|
let _ = self.try_wait(true);
|
||||||
let id = self.id() as c_int;
|
|
||||||
unsafe { libc::waitpid(id, &mut status, 0) };
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn poll_exit(&mut self) -> Poll<ExitStatus, io::Error> {
|
pub fn poll_exit(&mut self) -> Poll<ExitStatus, io::Error> {
|
||||||
assert!(!self.reaped);
|
|
||||||
loop {
|
loop {
|
||||||
// Ensure that once we've successfully waited we won't try to
|
// Ensure that once we've successfully waited we won't try to
|
||||||
// `kill` above.
|
// `kill` above.
|
||||||
if let Some(e) = try!(self.try_wait()) {
|
if let Some(e) = try!(self.try_wait(false)) {
|
||||||
self.reaped = true;
|
|
||||||
return Ok(e.into())
|
return Ok(e.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,23 +116,35 @@ impl Child {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_wait(&self) -> io::Result<Option<ExitStatus>> {
|
fn try_wait(&mut self, block_on_wait: bool) -> io::Result<Option<ExitStatus>> {
|
||||||
let id = self.id() as c_int;
|
assert!(!self.reaped);
|
||||||
let mut status = 0;
|
let exit = try!(try_wait_process(self.id() as libc::pid_t, block_on_wait));
|
||||||
loop {
|
|
||||||
match unsafe { libc::waitpid(id, &mut status, libc::WNOHANG) } {
|
if let Some(_) = exit {
|
||||||
0 => return Ok(None),
|
self.reaped = true;
|
||||||
n if n < 0 => {
|
}
|
||||||
let err = io::Error::last_os_error();
|
|
||||||
if err.kind() == io::ErrorKind::Interrupted {
|
Ok(exit)
|
||||||
continue
|
}
|
||||||
}
|
}
|
||||||
return Err(err)
|
|
||||||
}
|
fn try_wait_process(id: libc::pid_t, block_on_wait: bool) -> io::Result<Option<ExitStatus>> {
|
||||||
n => {
|
let wait_flags = if block_on_wait { 0 } else { libc::WNOHANG };
|
||||||
assert_eq!(n, id);
|
let mut status = 0;
|
||||||
return Ok(Some(ExitStatus::from_raw(status)))
|
|
||||||
|
loop {
|
||||||
|
match unsafe { libc::waitpid(id, &mut status, wait_flags) } {
|
||||||
|
0 => return Ok(None),
|
||||||
|
n if n < 0 => {
|
||||||
|
let err = io::Error::last_os_error();
|
||||||
|
if err.kind() == io::ErrorKind::Interrupted {
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
return Err(err)
|
||||||
|
}
|
||||||
|
n => {
|
||||||
|
assert_eq!(n, id);
|
||||||
|
return Ok(Some(ExitStatus::from_raw(status)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user