Skip to content

Commit 029d41f

Browse files
committed
fix: restore automatic unload on normal backend shutdown
Move the unload sequence back into a detached autouninstall child process so the backend can exit normally while still unloading OpenSysKit and DriverLoader automatically. Made-with: Cursor
1 parent 06fc1d6 commit 029d41f

2 files changed

Lines changed: 156 additions & 9 deletions

File tree

cmd/server/autouninstall_mode_windows.go

Lines changed: 142 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,149 @@ package main
44

55
import (
66
"fmt"
7+
"log"
8+
"os"
9+
"sort"
10+
"strconv"
11+
"strings"
12+
"time"
13+
14+
"github.com/OpenSysKit/backend/internal/driver"
715
)
816

917
func runAutoUninstallMode() error {
10-
return fmt.Errorf("autouninstall 已禁用:请使用显式 uninstall 命令执行完整卸载,避免主进程退出阶段蓝屏")
18+
delay := parseAutoUninstallDelay()
19+
handles, err := parseAutoUninstallHandles()
20+
if err != nil {
21+
return err
22+
}
23+
if len(handles) == 0 {
24+
return fmt.Errorf("autouninstall 未提供可卸载的 handle")
25+
}
26+
27+
log.Printf("autouninstall 子进程启动: delay=%s handles=%s", delay, formatHandleList(handles))
28+
if delay > 0 {
29+
time.Sleep(delay)
30+
}
31+
32+
log.Printf("autouninstall 开始执行完整卸载")
33+
if err := runAutoUninstall(handles); err != nil {
34+
return fmt.Errorf("autouninstall 卸载失败: %w", err)
35+
}
36+
log.Printf("autouninstall 卸载完成")
37+
return nil
38+
}
39+
40+
func runAutoUninstall(handles []uint64) error {
41+
loader, err := driver.OpenExistingLoader()
42+
if err != nil {
43+
return fmt.Errorf("autouninstall 无法连接 WinDrive(\\\\.\\DriverLoader): %w", err)
44+
}
45+
defer loader.Close()
46+
47+
drivers, err := loader.ListMappedDrivers()
48+
if err != nil {
49+
return err
50+
}
51+
if len(drivers) == 0 {
52+
log.Printf("autouninstall 未检测到映射驱动,跳过 OpenSysKit 卸载")
53+
} else {
54+
existing := make(map[uint64]struct{}, len(drivers))
55+
for _, row := range drivers {
56+
existing[row.Handle] = struct{}{}
57+
}
58+
59+
filtered := make([]uint64, 0, len(handles))
60+
for _, h := range dedupHandles(handles) {
61+
if _, ok := existing[h]; ok {
62+
filtered = append(filtered, h)
63+
} else {
64+
log.Printf("autouninstall 跳过不存在的 handle=%d (当前映射: %s)", h, formatHandles(drivers))
65+
}
66+
}
67+
if len(filtered) == 0 {
68+
return fmt.Errorf("autouninstall 指定 handle 均不存在,当前映射: %s", formatHandles(drivers))
69+
}
70+
71+
sort.Slice(filtered, func(i, j int) bool { return filtered[i] > filtered[j] })
72+
if waitForDeviceRelease(`\\.\OpenSysKit`, 15*time.Second) {
73+
log.Println("autouninstall 检测到设备引用已释放,开始卸载")
74+
} else {
75+
log.Println("autouninstall 警告: 设备可能仍被占用,仍尝试卸载")
76+
}
77+
78+
log.Printf("autouninstall 计划卸载 handle: %s", formatHandleList(filtered))
79+
for _, handle := range filtered {
80+
if err = unloadHandleWithRetry(loader, handle, 5); err != nil {
81+
return err
82+
}
83+
}
84+
}
85+
86+
after, err := loader.ListMappedDrivers()
87+
if err != nil {
88+
return err
89+
}
90+
if len(after) != 0 {
91+
return fmt.Errorf("autouninstall 卸载后仍存在映射驱动: %s", formatHandles(after))
92+
}
93+
94+
log.Println("autouninstall 下发 WinDrive allow-unload")
95+
if err = loader.AllowUnload(); err != nil {
96+
return err
97+
}
98+
99+
loader.Close()
100+
log.Println("autouninstall 卸载 DriverLoader 服务")
101+
if err = driver.UninstallLoaderService(); err != nil {
102+
return err
103+
}
104+
return nil
105+
}
106+
107+
func parseAutoUninstallDelay() time.Duration {
108+
for _, arg := range os.Args[2:] {
109+
if strings.HasPrefix(arg, "--delay=") {
110+
raw := strings.TrimSpace(strings.TrimPrefix(arg, "--delay="))
111+
if raw == "" {
112+
continue
113+
}
114+
seconds, err := strconv.Atoi(raw)
115+
if err != nil || seconds < 0 {
116+
log.Printf("警告: 非法 autouninstall delay 参数 %q,改用 1 秒", raw)
117+
return time.Second
118+
}
119+
if seconds == 0 {
120+
return 0
121+
}
122+
return time.Duration(seconds) * time.Second
123+
}
124+
}
125+
return time.Second
126+
}
127+
128+
func parseAutoUninstallHandles() ([]uint64, error) {
129+
for _, arg := range os.Args[2:] {
130+
if strings.HasPrefix(arg, "--handles=") {
131+
raw := strings.TrimSpace(strings.TrimPrefix(arg, "--handles="))
132+
if raw == "" {
133+
return nil, nil
134+
}
135+
parts := strings.Split(raw, ",")
136+
handles := make([]uint64, 0, len(parts))
137+
for _, part := range parts {
138+
part = strings.TrimSpace(part)
139+
if part == "" {
140+
continue
141+
}
142+
h, err := strconv.ParseUint(part, 10, 64)
143+
if err != nil {
144+
return nil, fmt.Errorf("解析 autouninstall handle 失败 %q: %w", part, err)
145+
}
146+
handles = append(handles, h)
147+
}
148+
return handles, nil
149+
}
150+
}
151+
return nil, nil
11152
}

cmd/server/main.go

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -192,15 +192,21 @@ func main() {
192192
loader = nil
193193
}
194194

195-
// 卸载不能再放在主进程退出阶段自动执行:
196-
// 在当前系统环境下会触发 KiSystemServiceExitPico / APC_INDEX_MISMATCH 蓝屏。
197-
// 因此这里只释放本进程句柄,并明确提示使用显式 uninstall 命令完成完整卸载链路。
195+
// 自动卸载仍由独立子进程执行,但主进程只负责调度并正常退出,
196+
// 避免在当前进程退出临界区直接执行卸载链路触发蓝屏。
197+
if !autoUninstallEnabled() {
198+
log.Printf("自动卸载已禁用: mapped_by_this_process=%t, handles=%s,请手动执行 OpenSysKit.exe uninstall", mappedByThisProcess, formatHandleList(mappedHandles))
199+
log.Println("主进程已完成资源释放,正常退出")
200+
return
201+
}
202+
198203
if mappedByThisProcess && len(mappedHandles) > 0 {
199-
log.Printf("已跳过退出阶段自动卸载以避免蓝屏: mapped_by_this_process=%t, handles=%s,请稍后手动执行 OpenSysKit.exe uninstall --handles=%s",
200-
mappedByThisProcess,
201-
formatHandleList(mappedHandles),
202-
formatHandleList(mappedHandles),
203-
)
204+
log.Printf("调度自动卸载子进程: handles=%s", formatHandleList(mappedHandles))
205+
if err := scheduleSelfUninstall(1*time.Second, mappedHandles); err != nil {
206+
log.Printf("警告: 调度自动卸载失败: %v,请手动执行 OpenSysKit.exe uninstall --handles=%s", err, formatHandleList(mappedHandles))
207+
} else {
208+
log.Printf("自动卸载子进程已启动,将执行 WinDrive 安全卸载链路: handles=%s", formatHandleList(mappedHandles))
209+
}
204210
} else {
205211
log.Printf("退出时无需卸载映射驱动: mapped_by_this_process=%t, handles=%s", mappedByThisProcess, formatHandleList(mappedHandles))
206212
}

0 commit comments

Comments
 (0)