removed unsafe codes on runc client and shim

Signed-off-by: Yuna Tomida <ytomida.mmm@gmail.com>
This commit is contained in:
Yuna Tomida 2022-05-04 15:39:41 +09:00
parent 5173325a90
commit f9ae07236d
No known key found for this signature in database
GPG Key ID: E6EC40A47CA07A6F
3 changed files with 73 additions and 41 deletions

View File

@ -19,7 +19,7 @@ use std::io::Result;
#[cfg(not(feature = "async"))] #[cfg(not(feature = "async"))]
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::os::unix::fs::OpenOptionsExt; use std::os::unix::fs::OpenOptionsExt;
use std::os::unix::io::{AsRawFd, FromRawFd}; use std::os::unix::io::AsRawFd;
use std::process::Stdio; use std::process::Stdio;
use std::sync::Mutex; use std::sync::Mutex;
@ -253,12 +253,8 @@ pub struct NullIo {
impl NullIo { impl NullIo {
pub fn new() -> std::io::Result<Self> { pub fn new() -> std::io::Result<Self> {
let fd = nix::fcntl::open( let f = OpenOptions::new().read(true).open("/dev/null")?;
"/dev/null", let dev_null = Mutex::new(Some(f));
nix::fcntl::OFlag::O_RDONLY,
nix::sys::stat::Mode::empty(),
)?;
let dev_null = unsafe { Mutex::new(Some(std::fs::File::from_raw_fd(fd))) };
Ok(Self { dev_null }) Ok(Self { dev_null })
} }
} }

View File

@ -14,6 +14,7 @@
limitations under the License. limitations under the License.
*/ */
use std::convert::TryFrom;
use std::os::unix::fs::FileTypeExt; use std::os::unix::fs::FileTypeExt;
use std::os::unix::io::AsRawFd; use std::os::unix::io::AsRawFd;
use std::os::unix::net::UnixListener; use std::os::unix::net::UnixListener;
@ -27,8 +28,12 @@ use std::{env, process};
use async_trait::async_trait; use async_trait::async_trait;
use command_fds::{CommandFdExt, FdMapping}; use command_fds::{CommandFdExt, FdMapping};
use futures::StreamExt; use futures::StreamExt;
use libc::{c_int, pid_t, SIGCHLD, SIGINT, SIGPIPE, SIGTERM}; use libc::{SIGCHLD, SIGINT, SIGPIPE, SIGTERM};
use log::{debug, error, info, warn}; use log::{debug, error, info, warn};
use nix::errno::Errno;
use nix::sys::signal::Signal;
use nix::sys::wait::{self, WaitPidFlag, WaitStatus};
use nix::unistd::Pid;
use signal_hook_tokio::Signals; use signal_hook_tokio::Signals;
use tokio::io::AsyncWriteExt; use tokio::io::AsyncWriteExt;
use tokio::sync::Notify; use tokio::sync::Notify;
@ -304,28 +309,43 @@ async fn handle_signals(signals: Signals) {
debug!("received {}", sig); debug!("received {}", sig);
} }
SIGCHLD => loop { SIGCHLD => loop {
let result = asyncify(move || -> Result<(pid_t, c_int)> { // Note: see comment at the counterpart in synchronous/mod.rs for details.
let mut status: c_int = -1; match asyncify(move || {
let pid = unsafe { libc::waitpid(-1, &mut status, libc::WNOHANG) }; Ok(wait::waitpid(
if pid <= 0 { Some(Pid::from_raw(-1)),
return Err(other!("wait finished")); Some(WaitPidFlag::WNOHANG),
} )?)
let status = libc::WEXITSTATUS(status);
Ok((pid, status))
}) })
.await; .await
{
if let Ok((res_pid, status)) = result { Ok(WaitStatus::Exited(pid, status)) => {
monitor_notify_by_pid(res_pid, status) monitor_notify_by_pid(pid.as_raw(), status)
.await .await
.unwrap_or_else(|e| { .unwrap_or_else(|e| error!("failed to send exit event {}", e))
error!("failed to send pid exit event {}", e); }
}) Ok(WaitStatus::Signaled(pid, sig, _)) => {
} else { debug!("child {} terminated({})", pid, sig);
break; let exit_code = 128 + sig as i32;
monitor_notify_by_pid(pid.as_raw(), exit_code)
.await
.unwrap_or_else(|e| error!("failed to send signal event {}", e))
}
Err(Error::Nix(Errno::ECHILD)) => {
break;
}
Err(e) => {
warn!("error occurred in signal handler: {}", e);
}
_ => {}
} }
}, },
_ => {} _ => {
if let Ok(sig) = Signal::try_from(sig) {
debug!("received {}", sig);
} else {
warn!("received invalid signal {}", sig);
}
}
} }
} }
} }

View File

@ -32,6 +32,7 @@
//! ``` //! ```
//! //!
use std::convert::TryFrom;
use std::env; use std::env;
use std::fs; use std::fs;
use std::io::Write; use std::io::Write;
@ -42,8 +43,12 @@ use std::process::{self, Command, Stdio};
use std::sync::{Arc, Condvar, Mutex}; use std::sync::{Arc, Condvar, Mutex};
use command_fds::{CommandFdExt, FdMapping}; use command_fds::{CommandFdExt, FdMapping};
use libc::{c_int, pid_t, SIGCHLD, SIGINT, SIGPIPE, SIGTERM}; use libc::{SIGCHLD, SIGINT, SIGPIPE, SIGTERM};
pub use log::{debug, error, info, warn}; pub use log::{debug, error, info, warn};
use nix::errno::Errno;
use nix::sys::signal::Signal;
use nix::sys::wait::{self, WaitPidFlag, WaitStatus};
use nix::unistd::Pid;
use signal_hook::iterator::Signals; use signal_hook::iterator::Signals;
use crate::protos::protobuf::Message; use crate::protos::protobuf::Message;
@ -230,23 +235,34 @@ fn handle_signals(mut signals: Signals) {
debug!("received {}", sig); debug!("received {}", sig);
} }
SIGCHLD => loop { SIGCHLD => loop {
unsafe { // Note that this thread sticks to child even it is suspended.
let pid: pid_t = -1; match wait::waitpid(Some(Pid::from_raw(-1)), Some(WaitPidFlag::WNOHANG)) {
let mut status: c_int = 0; Ok(WaitStatus::Exited(pid, status)) => {
let options: c_int = libc::WNOHANG; monitor::monitor_notify_by_pid(pid.as_raw(), status)
let res_pid = libc::waitpid(pid, &mut status, options); .unwrap_or_else(|e| error!("failed to send exit event {}", e))
let status = libc::WEXITSTATUS(status);
if res_pid <= 0 {
break;
} else {
monitor::monitor_notify_by_pid(res_pid, status).unwrap_or_else(|e| {
error!("failed to send exit event {}", e);
});
} }
Ok(WaitStatus::Signaled(pid, sig, _)) => {
debug!("child {} terminated({})", pid, sig);
let exit_code = 128 + sig as i32;
monitor::monitor_notify_by_pid(pid.as_raw(), exit_code)
.unwrap_or_else(|e| error!("failed to send signal event {}", e))
}
Err(Errno::ECHILD) => {
break;
}
Err(e) => {
// stick until all children will be successfully waited, even some unexpected error occurs.
warn!("error occurred in signal handler: {}", e);
}
_ => {} // stick until exit
} }
}, },
_ => { _ => {
debug!("received {}", sig); if let Ok(sig) = Signal::try_from(sig) {
debug!("received {}", sig);
} else {
warn!("received invalid signal {}", sig);
}
} }
} }
} }