aboutsummaryrefslogtreecommitdiffstats
path: root/src/reload.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/reload.rs')
-rw-r--r--src/reload.rs46
1 files changed, 46 insertions, 0 deletions
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());
+ }
+}