aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/main.rs40
-rw-r--r--src/reload.rs46
-rw-r--r--src/run/builtin.rs8
-rw-r--r--src/run/mod.rs5
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);