kanit

Toy init system
Log | Files | Refs | README | LICENSE

ev_loop.rs (2276B)


      1 use async_fs::File;
      2 use async_signal::{Signal, Signals};
      3 use futures_lite::{AsyncReadExt, StreamExt};
      4 use log::debug;
      5 use nix::errno::Errno;
      6 use nix::sys::reboot::RebootMode;
      7 use nix::sys::stat::Mode;
      8 use nix::unistd::mkfifo;
      9 
     10 use kanit_common::constants;
     11 use kanit_common::error::{Context, Result};
     12 use kanit_executor::{block, spawn};
     13 
     14 use crate::{event_rc, teardown};
     15 
     16 async fn pipe_handler(data: Vec<u8>) -> Result<()> {
     17     if data.starts_with(b"halt") {
     18         teardown(Some(RebootMode::RB_HALT_SYSTEM))?;
     19     } else if data.starts_with(b"poweroff") {
     20         teardown(Some(RebootMode::RB_POWER_OFF))?;
     21     } else if data.starts_with(b"reboot") {
     22         teardown(Some(RebootMode::RB_AUTOBOOT))?;
     23     } else if data.starts_with(b"kexec") {
     24         teardown(Some(RebootMode::RB_KEXEC))?;
     25     } else {
     26         event_rc(data).await?;
     27     }
     28 
     29     Ok(())
     30 }
     31 
     32 async fn listen_signal() -> Result<()> {
     33     let mut signals = Signals::new([Signal::Int, Signal::Term, Signal::Child])
     34         .context("failed to register signals")?;
     35 
     36     while let Some(signal) = signals.next().await {
     37         let signal = if let Ok(signal) = signal {
     38             signal
     39         } else {
     40             continue;
     41         };
     42 
     43         debug!("*boop* {signal:?}");
     44     }
     45 
     46     Ok(())
     47 }
     48 
     49 async fn listen_file() -> Result<()> {
     50     mkfifo(constants::KAN_PIPE, Mode::S_IRUSR | Mode::S_IWUSR).context("failed to create pipe")?;
     51 
     52     loop {
     53         let mut buff = vec![0u8; 512];
     54 
     55         let mut file = match File::open(constants::KAN_PIPE).await {
     56             Ok(f) => f,
     57             Err(e) => match e.raw_os_error() {
     58                 None => return Err(e.into()),
     59                 Some(n) => {
     60                     if Errno::from_raw(n) == Errno::EINTR {
     61                         continue;
     62                     } else {
     63                         return Err(e.into());
     64                     }
     65                 }
     66             },
     67         };
     68 
     69         file.read(&mut buff).await.context("failed to read pipe")?;
     70 
     71         spawn(pipe_handler(buff)).detach();
     72     }
     73 }
     74 
     75 async fn inner_ev_loop() -> Result<()> {
     76     let handles = [spawn(listen_signal()), spawn(listen_file())];
     77 
     78     for handle in handles {
     79         handle.await?;
     80     }
     81 
     82     Ok(())
     83 }
     84 
     85 pub fn ev_loop() -> Result<()> {
     86     block(inner_ev_loop())?;
     87 
     88     Ok(())
     89 }