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 nix::unistd::Pid;
|
||||||
use tokio;
|
use tokio;
|
||||||
|
|
||||||
fn sigint_handler() {
|
fn shutdown_handler() {
|
||||||
println!("Received signal SIGINT");
|
println!("stopping services");
|
||||||
process::exit(0);
|
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() {
|
fn reap_handler() {
|
||||||
loop {
|
loop {
|
||||||
|
@ -51,7 +78,7 @@ fn set_hostname() {
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Box<dyn Error>> {
|
async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
|
||||||
|
if process::id() == 1 {
|
||||||
println!("mini, the bare minimum init by darkgallium");
|
println!("mini, the bare minimum init by darkgallium");
|
||||||
println!();
|
println!();
|
||||||
|
|
||||||
|
@ -85,41 +112,29 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
processes::run("mkdir", ["/run/dbus"].as_ref()).await;
|
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
|
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 = 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");
|
println!("end bootstrap, launching your terminals");
|
||||||
|
|
||||||
// TODO: spawn a thread by tty and join threads at end
|
tokio::spawn(async {
|
||||||
processes::sync_run_wait("agetty", ["--noclear", "tty1"].as_ref());
|
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");
|
} else {
|
||||||
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::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(())
|
Ok(())
|
||||||
|
|
25
src/svc.rs
25
src/svc.rs
|
@ -1,5 +1,6 @@
|
||||||
use std::{fs, path::Path};
|
use std::{fs, path::Path};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
use std::collections::BTreeMap;
|
||||||
use toml;
|
use toml;
|
||||||
use tokio;
|
use tokio;
|
||||||
use crate::processes;
|
use crate::processes;
|
||||||
|
@ -7,6 +8,7 @@ use crate::processes;
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
pub struct Service {
|
pub struct Service {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
pub level: u16,
|
||||||
pub start: Start,
|
pub start: Start,
|
||||||
pub stop: Option<Stop>,
|
pub stop: Option<Stop>,
|
||||||
}
|
}
|
||||||
|
@ -23,8 +25,9 @@ pub struct Stop {
|
||||||
pub args: Vec<String>
|
pub args: Vec<String>
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_services() -> Vec<Service> {
|
pub fn get_services() -> BTreeMap<u16, Vec<Service>> {
|
||||||
let mut services = Vec::new();
|
let mut services = BTreeMap::new();
|
||||||
|
//let mut services = Vec::new();
|
||||||
let mini_dir = Path::new("/etc/mini/");
|
let mini_dir = Path::new("/etc/mini/");
|
||||||
|
|
||||||
if mini_dir.exists() && mini_dir.is_dir() {
|
if mini_dir.exists() && mini_dir.is_dir() {
|
||||||
|
@ -35,7 +38,9 @@ pub fn get_services() -> Vec<Service> {
|
||||||
// TODO: check ext
|
// TODO: check ext
|
||||||
let svc_file_contents = fs::read_to_string(file.unwrap().path()).unwrap();
|
let svc_file_contents = fs::read_to_string(file.unwrap().path()).unwrap();
|
||||||
let svc : Service = toml::from_str(&svc_file_contents).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() {
|
pub async fn launch_services() {
|
||||||
let services = get_services();
|
let services = get_services();
|
||||||
|
|
||||||
for s in services {
|
for (level, svc_list) in services {
|
||||||
|
for s in svc_list {
|
||||||
tokio::spawn(async move {
|
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();
|
let args: Vec<&str> = s.start.args.iter().map(|e| e.as_str()).collect();
|
||||||
processes::run(&s.start.command, &args[..]).await;
|
processes::run(&s.start.command, &args[..]).await;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn stop_services() {
|
pub fn stop_services() {
|
||||||
let services = get_services();
|
let services = get_services();
|
||||||
|
|
||||||
for s in services {
|
for (level, svc_list) in services.iter().rev() {
|
||||||
println!("stopping {}", s.name);
|
for s in svc_list {
|
||||||
if let Some(stop) = s.stop {
|
println!("stopping {}[{}]", s.name, level);
|
||||||
|
if let Some(stop) = &s.stop {
|
||||||
let args: Vec<&str> = stop.args.iter().map(|e| e.as_str()).collect();
|
let args: Vec<&str> = stop.args.iter().map(|e| e.as_str()).collect();
|
||||||
processes::sync_run_wait(&stop.command, &args[..]);
|
processes::sync_run_wait(&stop.command, &args[..]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue