adding runlevels & fixing unpredictable loading order
This commit is contained in:
parent
06b4d1bf10
commit
9e75ea95c8
2 changed files with 106 additions and 82 deletions
79
src/main.rs
79
src/main.rs
|
@ -14,10 +14,37 @@ use nix::sys::signal::kill;
|
|||
use nix::unistd::Pid;
|
||||
use tokio;
|
||||
|
||||
fn sigint_handler() {
|
||||
println!("Received signal SIGINT");
|
||||
process::exit(0);
|
||||
fn shutdown_handler() {
|
||||
println!("stopping services");
|
||||
svc::stop_services();
|
||||
|
||||
println!("killing remaining processes");
|
||||
let pids = processes::get_all_pids();
|
||||
|
||||
for pid in pids {
|
||||
let res = kill(Pid::from_raw(pid), Signal::SIGKILL);
|
||||
match res {
|
||||
Ok(_) => {}
|
||||
Err(err) => eprintln!("error killing process {}, error is {}", pid, err)
|
||||
}
|
||||
}
|
||||
|
||||
println!("unmounting all partitions");
|
||||
processes::sync_run_wait("swapoff", ["-a"].as_ref());
|
||||
processes::sync_run_wait("umount", ["-a", "-f"].as_ref());
|
||||
|
||||
println!("syncing disks");
|
||||
processes::sync_run_wait("sync", [].as_ref());
|
||||
|
||||
println!("end pre-shutdown routines");
|
||||
|
||||
#[allow(unused_must_use)] {
|
||||
reboot(RebootMode::RB_POWER_OFF);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
fn reap_handler() {
|
||||
loop {
|
||||
|
@ -51,7 +78,7 @@ fn set_hostname() {
|
|||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn Error>> {
|
||||
|
||||
|
||||
if process::id() == 1 {
|
||||
println!("mini, the bare minimum init by darkgallium");
|
||||
println!();
|
||||
|
||||
|
@ -85,41 +112,29 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
|||
processes::run("mkdir", ["/run/dbus"].as_ref()).await;
|
||||
processes::run("dbus-daemon", ["--system"].as_ref()).await; // a lot of services depend on dbus being on
|
||||
|
||||
println!("now loading your services");
|
||||
svc::launch_services().await;
|
||||
|
||||
unsafe { signal_hook::register(SIGINT, sigint_handler) }?;
|
||||
let sigchld_handle = unsafe { signal_hook::register(SIGCHLD, reap_handler) }?;
|
||||
let sigchld_handle_c = sigchld_handle.clone();
|
||||
|
||||
unsafe { signal_hook::register(SIGINT, move || {
|
||||
signal_hook::unregister(sigchld_handle);
|
||||
shutdown_handler();
|
||||
}) }?;
|
||||
|
||||
|
||||
println!("loading services");
|
||||
svc::launch_services().await;
|
||||
|
||||
println!("end bootstrap, launching your terminals");
|
||||
|
||||
// TODO: spawn a thread by tty and join threads at end
|
||||
processes::sync_run_wait("agetty", ["--noclear", "tty1"].as_ref());
|
||||
tokio::spawn(async {
|
||||
processes::run("agetty", ["--noclear", "tty1"].as_ref()).await;
|
||||
}).await;
|
||||
|
||||
signal_hook::unregister(sigchld_handle);
|
||||
signal_hook::unregister(sigchld_handle_c);
|
||||
shutdown_handler();
|
||||
|
||||
println!("stopping services");
|
||||
svc::stop_services();
|
||||
} else {
|
||||
|
||||
println!("killing remaining processes");
|
||||
let pids = processes::get_all_pids();
|
||||
|
||||
for pid in pids {
|
||||
let res = kill(Pid::from_raw(pid), Signal::SIGKILL);
|
||||
match res {
|
||||
Ok(_) => {}
|
||||
Err(err) => eprintln!("error killing process {}, error is {}", pid, err)
|
||||
}
|
||||
}
|
||||
|
||||
println!("unmounting all partitions");
|
||||
processes::run("swapoff", ["-a"].as_ref()).await;
|
||||
processes::run("umount", ["-a", "-f"].as_ref()).await;
|
||||
|
||||
println!("end pre-shutdown routines");
|
||||
|
||||
#[allow(unused_must_use)] {
|
||||
reboot(RebootMode::RB_POWER_OFF);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
25
src/svc.rs
25
src/svc.rs
|
@ -1,5 +1,6 @@
|
|||
use std::{fs, path::Path};
|
||||
use serde::Deserialize;
|
||||
use std::collections::BTreeMap;
|
||||
use toml;
|
||||
use tokio;
|
||||
use crate::processes;
|
||||
|
@ -7,6 +8,7 @@ use crate::processes;
|
|||
#[derive(Deserialize, Debug)]
|
||||
pub struct Service {
|
||||
pub name: String,
|
||||
pub level: u16,
|
||||
pub start: Start,
|
||||
pub stop: Option<Stop>,
|
||||
}
|
||||
|
@ -23,8 +25,9 @@ pub struct Stop {
|
|||
pub args: Vec<String>
|
||||
}
|
||||
|
||||
pub fn get_services() -> Vec<Service> {
|
||||
let mut services = Vec::new();
|
||||
pub fn get_services() -> BTreeMap<u16, Vec<Service>> {
|
||||
let mut services = BTreeMap::new();
|
||||
//let mut services = Vec::new();
|
||||
let mini_dir = Path::new("/etc/mini/");
|
||||
|
||||
if mini_dir.exists() && mini_dir.is_dir() {
|
||||
|
@ -35,7 +38,9 @@ pub fn get_services() -> Vec<Service> {
|
|||
// TODO: check ext
|
||||
let svc_file_contents = fs::read_to_string(file.unwrap().path()).unwrap();
|
||||
let svc : Service = toml::from_str(&svc_file_contents).unwrap();
|
||||
services.push(svc);
|
||||
|
||||
let lvl = services.entry(svc.level).or_insert(Vec::new());
|
||||
lvl.push(svc);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -46,23 +51,27 @@ pub fn get_services() -> Vec<Service> {
|
|||
pub async fn launch_services() {
|
||||
let services = get_services();
|
||||
|
||||
for s in services {
|
||||
for (level, svc_list) in services {
|
||||
for s in svc_list {
|
||||
tokio::spawn(async move {
|
||||
println!("starting {}", s.name);
|
||||
println!("starting {}[{}]", s.name, level);
|
||||
let args: Vec<&str> = s.start.args.iter().map(|e| e.as_str()).collect();
|
||||
processes::run(&s.start.command, &args[..]).await;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stop_services() {
|
||||
let services = get_services();
|
||||
|
||||
for s in services {
|
||||
println!("stopping {}", s.name);
|
||||
if let Some(stop) = s.stop {
|
||||
for (level, svc_list) in services.iter().rev() {
|
||||
for s in svc_list {
|
||||
println!("stopping {}[{}]", s.name, level);
|
||||
if let Some(stop) = &s.stop {
|
||||
let args: Vec<&str> = stop.args.iter().map(|e| e.as_str()).collect();
|
||||
processes::sync_run_wait(&stop.command, &args[..]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue