Преглед на файлове

Merge pull request #1060 from Demonthos/fix-macos-hot-reloading

Fix restarting MacOs hot reloading after a forced exit
Jon Kelley преди 2 години
родител
ревизия
07dd9c275f
променени са 1 файла, в които са добавени 157 реда и са изтрити 139 реда
  1. 157 139
      packages/hot-reload/src/lib.rs

+ 157 - 139
packages/hot-reload/src/lib.rs

@@ -159,172 +159,190 @@ pub fn init<Ctx: HotReloadingContext + Send + 'static>(cfg: Config<Ctx>) {
         }
         let file_map = Arc::new(Mutex::new(file_map));
 
-        if let Ok(local_socket_stream) = LocalSocketListener::bind("@dioxusin") {
-            let aborted = Arc::new(Mutex::new(false));
-
-            // listen for connections
-            std::thread::spawn({
-                let file_map = file_map.clone();
-                let channels = channels.clone();
-                let aborted = aborted.clone();
-                let _ = local_socket_stream.set_nonblocking(true);
-                move || {
-                    loop {
-                        if let Ok(mut connection) = local_socket_stream.accept() {
-                            // send any templates than have changed before the socket connected
-                            let templates: Vec<_> = {
-                                file_map
-                                    .lock()
-                                    .unwrap()
-                                    .map
-                                    .values()
-                                    .filter_map(|(_, template_slot)| *template_slot)
-                                    .collect()
-                            };
-                            for template in templates {
-                                if !send_msg(
-                                    HotReloadMsg::UpdateTemplate(template),
-                                    &mut connection,
-                                ) {
-                                    continue;
+        #[cfg(target_os = "macos")]
+        {
+            // On unix, if you force quit the application, it can leave the file socket open
+            // This will cause the local socket listener to fail to open
+            // We check if the file socket is already open from an old session and then delete it
+            let paths = ["./dioxusin", "./@dioxusin"];
+            for path in paths {
+                let path = PathBuf::from(path);
+                if path.exists() {
+                    let _ = std::fs::remove_file(path);
+                }
+            }
+        }
+
+        match LocalSocketListener::bind("@dioxusin") {
+            Ok(local_socket_stream) => {
+                let aborted = Arc::new(Mutex::new(false));
+
+                // listen for connections
+                std::thread::spawn({
+                    let file_map = file_map.clone();
+                    let channels = channels.clone();
+                    let aborted = aborted.clone();
+                    let _ = local_socket_stream.set_nonblocking(true);
+                    move || {
+                        loop {
+                            if let Ok(mut connection) = local_socket_stream.accept() {
+                                // send any templates than have changed before the socket connected
+                                let templates: Vec<_> = {
+                                    file_map
+                                        .lock()
+                                        .unwrap()
+                                        .map
+                                        .values()
+                                        .filter_map(|(_, template_slot)| *template_slot)
+                                        .collect()
+                                };
+                                for template in templates {
+                                    if !send_msg(
+                                        HotReloadMsg::UpdateTemplate(template),
+                                        &mut connection,
+                                    ) {
+                                        continue;
+                                    }
+                                }
+                                channels.lock().unwrap().push(connection);
+                                if log {
+                                    println!("Connected to hot reloading 🚀");
                                 }
                             }
-                            channels.lock().unwrap().push(connection);
-                            if log {
-                                println!("Connected to hot reloading 🚀");
+                            if *aborted.lock().unwrap() {
+                                break;
                             }
                         }
-                        if *aborted.lock().unwrap() {
-                            break;
-                        }
                     }
-                }
-            });
+                });
 
-            // watch for changes
-            std::thread::spawn(move || {
-                let mut last_update_time = chrono::Local::now().timestamp();
+                // watch for changes
+                std::thread::spawn(move || {
+                    let mut last_update_time = chrono::Local::now().timestamp();
 
-                let (tx, rx) = std::sync::mpsc::channel();
+                    let (tx, rx) = std::sync::mpsc::channel();
 
-                let mut watcher = RecommendedWatcher::new(tx, notify::Config::default()).unwrap();
+                    let mut watcher =
+                        RecommendedWatcher::new(tx, notify::Config::default()).unwrap();
 
-                for path in listening_paths {
-                    let full_path = crate_dir.join(path);
-                    if let Err(err) = watcher.watch(&full_path, RecursiveMode::Recursive) {
-                        if log {
-                            println!(
-                                "hot reloading failed to start watching {full_path:?}:\n{err:?}",
-                            );
+                    for path in listening_paths {
+                        let full_path = crate_dir.join(path);
+                        if let Err(err) = watcher.watch(&full_path, RecursiveMode::Recursive) {
+                            if log {
+                                println!(
+                                    "hot reloading failed to start watching {full_path:?}:\n{err:?}",
+                                );
+                            }
                         }
                     }
-                }
 
-                let mut rebuild = {
-                    let aborted = aborted.clone();
-                    let channels = channels.clone();
-                    move || {
-                        if let Some(rebuild_callback) = &mut rebuild_with {
-                            if log {
-                                println!("Rebuilding the application...");
-                            }
-                            let shutdown = rebuild_callback();
+                    let mut rebuild = {
+                        let aborted = aborted.clone();
+                        let channels = channels.clone();
+                        move || {
+                            if let Some(rebuild_callback) = &mut rebuild_with {
+                                if log {
+                                    println!("Rebuilding the application...");
+                                }
+                                let shutdown = rebuild_callback();
 
-                            if shutdown {
-                                *aborted.lock().unwrap() = true;
-                            }
+                                if shutdown {
+                                    *aborted.lock().unwrap() = true;
+                                }
 
-                            for channel in &mut *channels.lock().unwrap() {
-                                send_msg(HotReloadMsg::Shutdown, channel);
-                            }
+                                for channel in &mut *channels.lock().unwrap() {
+                                    send_msg(HotReloadMsg::Shutdown, channel);
+                                }
 
-                            return shutdown;
-                        } else if log {
-                            println!(
-                                "Rebuild needed... shutting down hot reloading.\nManually rebuild the application to view futher changes."
-                            );
-                        }
-                        true
-                    }
-                };
-
-                for evt in rx {
-                    if chrono::Local::now().timestamp_millis() >= last_update_time {
-                        if let Ok(evt) = evt {
-                            let real_paths = evt
-                                .paths
-                                .iter()
-                                .filter(|path| {
-                                    // skip non rust files
-                                    matches!(
-                                        path.extension().and_then(|p| p.to_str()),
-                                        Some("rs" | "toml" | "css" | "html" | "js")
-                                    ) &&
-                                    // skip excluded paths
-                                    !excluded_paths.iter().any(|p| path.starts_with(p)) &&
-                                    // respect .gitignore
-                                    !gitignore
-                                        .matched_path_or_any_parents(path, false)
-                                        .is_ignore()
-                                })
-                                .collect::<Vec<_>>();
-
-                            // Give time for the change to take effect before reading the file
-                            if !real_paths.is_empty() {
-                                std::thread::sleep(std::time::Duration::from_millis(10));
+                                return shutdown;
+                            } else if log {
+                                println!(
+                                    "Rebuild needed... shutting down hot reloading.\nManually rebuild the application to view futher changes."
+                                );
                             }
-
-                            let mut channels = channels.lock().unwrap();
-                            for path in real_paths {
-                                // if this file type cannot be hot reloaded, rebuild the application
-                                if path.extension().and_then(|p| p.to_str()) != Some("rs")
-                                    && rebuild()
-                                {
-                                    return;
+                            true
+                        }
+                    };
+
+                    for evt in rx {
+                        if chrono::Local::now().timestamp_millis() >= last_update_time {
+                            if let Ok(evt) = evt {
+                                let real_paths = evt
+                                    .paths
+                                    .iter()
+                                    .filter(|path| {
+                                        // skip non rust files
+                                        matches!(
+                                            path.extension().and_then(|p| p.to_str()),
+                                            Some("rs" | "toml" | "css" | "html" | "js")
+                                        ) &&
+                                        // skip excluded paths
+                                        !excluded_paths.iter().any(|p| path.starts_with(p)) &&
+                                        // respect .gitignore
+                                        !gitignore
+                                            .matched_path_or_any_parents(path, false)
+                                            .is_ignore()
+                                    })
+                                    .collect::<Vec<_>>();
+
+                                // Give time for the change to take effect before reading the file
+                                if !real_paths.is_empty() {
+                                    std::thread::sleep(std::time::Duration::from_millis(10));
                                 }
-                                // find changes to the rsx in the file
-                                match file_map
-                                    .lock()
-                                    .unwrap()
-                                    .update_rsx(path, crate_dir.as_path())
-                                {
-                                    Ok(UpdateResult::UpdatedRsx(msgs)) => {
-                                        for msg in msgs {
-                                            let mut i = 0;
-                                            while i < channels.len() {
-                                                let channel = &mut channels[i];
-                                                if send_msg(
-                                                    HotReloadMsg::UpdateTemplate(msg),
-                                                    channel,
-                                                ) {
-                                                    i += 1;
-                                                } else {
-                                                    channels.remove(i);
+
+                                let mut channels = channels.lock().unwrap();
+                                for path in real_paths {
+                                    // if this file type cannot be hot reloaded, rebuild the application
+                                    if path.extension().and_then(|p| p.to_str()) != Some("rs")
+                                        && rebuild()
+                                    {
+                                        return;
+                                    }
+                                    // find changes to the rsx in the file
+                                    match file_map
+                                        .lock()
+                                        .unwrap()
+                                        .update_rsx(path, crate_dir.as_path())
+                                    {
+                                        Ok(UpdateResult::UpdatedRsx(msgs)) => {
+                                            for msg in msgs {
+                                                let mut i = 0;
+                                                while i < channels.len() {
+                                                    let channel = &mut channels[i];
+                                                    if send_msg(
+                                                        HotReloadMsg::UpdateTemplate(msg),
+                                                        channel,
+                                                    ) {
+                                                        i += 1;
+                                                    } else {
+                                                        channels.remove(i);
+                                                    }
                                                 }
                                             }
                                         }
-                                    }
-                                    Ok(UpdateResult::NeedsRebuild) => {
-                                        drop(channels);
-                                        if rebuild() {
-                                            return;
+                                        Ok(UpdateResult::NeedsRebuild) => {
+                                            drop(channels);
+                                            if rebuild() {
+                                                return;
+                                            }
+                                            break;
                                         }
-                                        break;
-                                    }
-                                    Err(err) => {
-                                        if log {
-                                            println!(
-                                                "hot reloading failed to update rsx:\n{err:?}"
-                                            );
+                                        Err(err) => {
+                                            if log {
+                                                println!(
+                                                    "hot reloading failed to update rsx:\n{err:?}"
+                                                );
+                                            }
                                         }
                                     }
                                 }
                             }
+                            last_update_time = chrono::Local::now().timestamp_millis();
                         }
-                        last_update_time = chrono::Local::now().timestamp_millis();
                     }
-                }
-            });
+                });
+            }
+            Err(error) => println!("failed to connect to hot reloading\n{error}"),
         }
     }
 }