aboutsummaryrefslogtreecommitdiffstats
path: root/src/reload.rs
blob: effc8fd6a7e54ad9d77530c71823b7926ae14a6a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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());
    }
}