diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.rs | 40 | ||||
| -rw-r--r-- | src/reload.rs | 46 | ||||
| -rw-r--r-- | src/run/builtin.rs | 8 | ||||
| -rw-r--r-- | src/run/mod.rs | 5 |
4 files changed, 51 insertions, 48 deletions
diff --git a/src/main.rs b/src/main.rs index 6687937..b064fcb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,6 +11,7 @@ pub mod panic; pub mod parse; pub mod raw; pub mod run; +pub mod reload; use linebuf::LineBuf; use raw::*; @@ -248,35 +249,6 @@ fn event_loop() { se.raw.disable(); } -#[cfg(debug_assertions)] -fn reload_shell() { - use std::{env, ffi::CString, ptr}; - - // path to this executable - let exe = env::current_exe().unwrap(); - let exe_c = CString::new(exe.as_os_str().as_bytes()).unwrap(); - - // argv - let args: Vec<CString> = env::args().map(|a| CString::new(a).unwrap()).collect(); - - let mut argv: Vec<*const libc::c_char> = args.iter().map(|a| a.as_ptr()).collect(); - argv.push(ptr::null()); - - // environment - let env: Vec<CString> = env::vars() - .map(|(k, v)| CString::new(format!("{}={}", k, v)).unwrap()) - .collect(); - - let mut envp: Vec<*const libc::c_char> = env.iter().map(|e| e.as_ptr()).collect(); - envp.push(ptr::null()); - - unsafe { - libc::execve(exe_c.as_ptr(), argv.as_ptr(), envp.as_ptr()); - } - - eprintln!("exec failed"); -} - fn main() { if !io::stdin().is_terminal() { println!("need to run in a tty"); @@ -290,14 +262,10 @@ fn main() { let res = std::panic::catch_unwind(event_loop); match res { Ok(_) => break, - Err(_) => - { + Err(_) => { #[cfg(debug_assertions)] - if run::RELOAD.load(std::sync::atomic::Ordering::SeqCst) { - reload_shell(); - println!("failed to reload shell"); - } - } + unsafe { reload::continue_reload() } + }, } } diff --git a/src/reload.rs b/src/reload.rs new file mode 100644 index 0000000..effc8fd --- /dev/null +++ b/src/reload.rs @@ -0,0 +1,46 @@ +use std::{ + env, + ffi::CString, + io::Write, + panic, ptr, + sync::atomic::{AtomicBool, Ordering}, +}; + +static RELOAD: AtomicBool = AtomicBool::new(false); + +pub fn begin_reload() { + RELOAD.store(true, Ordering::SeqCst); + panic::resume_unwind(Box::new(42)); +} + +/// ONLY TO BE CALLED FROM MAIN WHEN NOT A SINGLE RESOURCE IS HELD +pub unsafe fn continue_reload() { + if !RELOAD.load(Ordering::SeqCst) { + return; + } + + eprintln!("reloading..."); + let _ = std::io::stdout().lock().flush(); + + unsafe { exec() } + + eprintln!("exec failed."); +} + +unsafe fn exec() { + // path to this executable + let exe = env::current_exe() + .unwrap() + .to_string_lossy() + .replace(" (deleted)", ""); + let exe_c = CString::new(exe).unwrap(); + + // argv + let args: Vec<CString> = env::args().map(|a| CString::new(a).unwrap()).collect(); + let mut argv: Vec<*const libc::c_char> = args.iter().map(|a| a.as_ptr()).collect(); + argv.push(ptr::null()); + + unsafe { + libc::execv(exe_c.as_ptr(), argv.as_ptr()); + } +} diff --git a/src/run/builtin.rs b/src/run/builtin.rs index da6f4f2..5524fd7 100644 --- a/src/run/builtin.rs +++ b/src/run/builtin.rs @@ -43,13 +43,7 @@ impl Builtin for re { session.raw.disable(); match Command::new("cargo").arg("build").status() { Ok(status) if status.success() => { - // build of new shell succeeded - - // unwind the entire stack intentionally to free resources - // the catch handler will check the boolean and execve into - // the new executable - super::RELOAD.store(true, std::sync::atomic::Ordering::SeqCst); - std::panic::resume_unwind(Box::new(42)); + crate::reload::begin_reload(); } _ => (), } diff --git a/src/run/mod.rs b/src/run/mod.rs index 0000547..6484e30 100644 --- a/src/run/mod.rs +++ b/src/run/mod.rs @@ -2,17 +2,12 @@ use std::collections::HashMap; use std::fs; use std::os::unix::fs::PermissionsExt; use std::path::PathBuf; -#[cfg(debug_assertions)] -use std::sync::atomic::AtomicBool; use crate::parse::Ast; use crate::*; mod builtin; -#[cfg(debug_assertions)] -pub static RELOAD: AtomicBool = AtomicBool::new(false); - pub fn run(se: &mut Session, cmd: Vec<u8>) { let parsed = parse::do_parse(&cmd); |
