Skip to content

Commit 9125721

Browse files
committed
fix: 退出时等待后台线程结束,防止进程挂起
1 parent f19f3ca commit 9125721

2 files changed

Lines changed: 47 additions & 4 deletions

File tree

src/loader/frame_hook.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
use std::sync::atomic::{AtomicBool, Ordering};
2+
use std::sync::Mutex;
23

4+
use windows_sys::Win32::Foundation::HANDLE;
35
use windows_sys::Win32::System::Threading::Sleep;
46

57
use super::log::{log_info, log_warn};
68
use super::seh::call_mod_on_frame;
79
use super::state::STATE;
810

11+
struct SendHandle(HANDLE);
12+
unsafe impl Send for SendHandle {}
13+
914
static FRAME_THREAD_STARTED: AtomicBool = AtomicBool::new(false);
1015
static FRAME_THREAD_RUNNING: AtomicBool = AtomicBool::new(false);
16+
static FRAME_THREAD_HANDLE: Mutex<Option<SendHandle>> = Mutex::new(None);
1117

1218
extern "system" {
1319
fn CreateThread(
@@ -17,7 +23,9 @@ extern "system" {
1723
param: *mut std::ffi::c_void,
1824
flags: u32,
1925
id: *mut u32,
20-
) -> *mut std::ffi::c_void;
26+
) -> HANDLE;
27+
fn WaitForSingleObject(handle: HANDLE, milliseconds: u32) -> u32;
28+
fn CloseHandle(handle: HANDLE) -> i32;
2129
}
2230

2331
pub fn start_if_needed() {
@@ -49,12 +57,26 @@ pub fn start_if_needed() {
4957
log_warn("failed to start chumod_on_frame fallback thread");
5058
return;
5159
}
60+
if let Ok(mut h) = FRAME_THREAD_HANDLE.lock() {
61+
*h = Some(SendHandle(handle));
62+
}
5263
}
5364
log_info("chumod_on_frame fallback thread started (16ms interval)");
5465
}
5566

5667
pub fn stop() {
68+
if !FRAME_THREAD_STARTED.load(Ordering::SeqCst) {
69+
return;
70+
}
5771
FRAME_THREAD_RUNNING.store(false, Ordering::SeqCst);
72+
unsafe {
73+
if let Ok(mut h) = FRAME_THREAD_HANDLE.lock() {
74+
if let Some(SendHandle(handle)) = h.take() {
75+
WaitForSingleObject(handle, 2000);
76+
CloseHandle(handle);
77+
}
78+
}
79+
}
5880
FRAME_THREAD_STARTED.store(false, Ordering::SeqCst);
5981
}
6082

@@ -71,7 +93,6 @@ pub unsafe fn tick() {
7193
return;
7294
}
7395

74-
// 复制回调后释放锁,避免 Mod 回调里调用 Loader API 时发生锁重入。
7596
let frame_mods: Vec<_> = STATE
7697
.lock()
7798
.map(|state| {

src/loader/hot_reload.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ use std::fs::File;
33
use std::panic::{catch_unwind, AssertUnwindSafe};
44
use std::path::Path;
55
use std::sync::atomic::{AtomicBool, Ordering};
6+
use std::sync::Mutex;
67

7-
use windows_sys::Win32::Foundation::GetLastError;
8+
use windows_sys::Win32::Foundation::{GetLastError, HANDLE};
89
use windows_sys::Win32::System::LibraryLoader::{GetModuleHandleA, GetProcAddress, LoadLibraryA};
910
use windows_sys::Win32::System::Threading::Sleep;
1011

@@ -24,6 +25,11 @@ static MONITOR_STARTED: AtomicBool = AtomicBool::new(false);
2425
static MONITOR_RUNNING: AtomicBool = AtomicBool::new(false);
2526
static RELOAD_IN_PROGRESS: AtomicBool = AtomicBool::new(false);
2627

28+
struct SendHandle(HANDLE);
29+
unsafe impl Send for SendHandle {}
30+
31+
static MONITOR_THREAD_HANDLE: Mutex<Option<SendHandle>> = Mutex::new(None);
32+
2733
extern "system" {
2834
fn CreateDirectoryA(path: *const u8, security: *const std::ffi::c_void) -> i32;
2935
fn CreateThread(
@@ -33,8 +39,10 @@ extern "system" {
3339
param: *mut std::ffi::c_void,
3440
flags: u32,
3541
id: *mut u32,
36-
) -> *mut std::ffi::c_void;
42+
) -> HANDLE;
3743
fn FreeLibrary(module: *mut std::ffi::c_void) -> i32;
44+
fn WaitForSingleObject(handle: HANDLE, milliseconds: u32) -> u32;
45+
fn CloseHandle(handle: HANDLE) -> i32;
3846
}
3947

4048
pub fn is_reloading() -> bool {
@@ -75,12 +83,26 @@ pub fn start_monitor() {
7583
log_warn("failed to start reload.flag monitor thread");
7684
return;
7785
}
86+
if let Ok(mut h) = MONITOR_THREAD_HANDLE.lock() {
87+
*h = Some(SendHandle(handle));
88+
}
7889
}
7990
log_info("reload.flag monitor thread started");
8091
}
8192

8293
pub fn stop_monitor() {
94+
if !MONITOR_STARTED.load(Ordering::SeqCst) {
95+
return;
96+
}
8397
MONITOR_RUNNING.store(false, Ordering::SeqCst);
98+
unsafe {
99+
if let Ok(mut h) = MONITOR_THREAD_HANDLE.lock() {
100+
if let Some(SendHandle(handle)) = h.take() {
101+
WaitForSingleObject(handle, 2000);
102+
CloseHandle(handle);
103+
}
104+
}
105+
}
84106
MONITOR_STARTED.store(false, Ordering::SeqCst);
85107
}
86108

0 commit comments

Comments
 (0)