tino 0.1.20

tino: tiny init process (PID 1) for Docker/Kubernetes containers, written in Rust (tini alternative)
Documentation
use anyhow::{Context, Result};
use nix::{
    errno::Errno,
    sys::{
        signal::{
            SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV, SIGSYS, SIGTRAP, SigSet, Signal, kill, killpg,
        },
        signalfd::{SfdFlags, SignalFd},
    },
    unistd::Pid,
};
use tracing::warn;

const SIGNALS_EXCLUDED_FROM_SIGNALFD: &[Signal] =
    &[SIGFPE, SIGILL, SIGSEGV, SIGBUS, SIGABRT, SIGTRAP, SIGSYS];

pub(super) fn setup_signal_delivery() -> Result<(SigSet, SignalFd)> {
    let previous_mask = SigSet::thread_get_mask().context("sigprocmask")?;
    let mut block = SigSet::all();
    for &signal in SIGNALS_EXCLUDED_FROM_SIGNALFD {
        block.remove(signal);
    }
    block.thread_set_mask().context("sigprocmask")?;

    let signal_fd = SignalFd::with_flags(&block, SfdFlags::SFD_NONBLOCK | SfdFlags::SFD_CLOEXEC)
        .context("signalfd")?;

    Ok((previous_mask, signal_fd))
}

pub(super) fn signal_by_name(name: &str) -> Option<Signal> {
    crate::signals::signal_from_str(name)
}

pub(super) fn send_signal(pgid: bool, child: Pid, sig: Signal) {
    let res = if pgid {
        killpg(Pid::from_raw(child.as_raw()), sig)
    } else {
        kill(child, sig)
    };
    if let Err(e) = res
        && e != Errno::ESRCH
    {
        warn!("forward {:?} failed: {}", sig, e);
    }
}