fix(core): 老版本 Java 按版本距离选 + 启动看门狗有界等待 + 结束归属(M214 D4/D6/D10)
D4:`pick` 的排序键从「来源序」改成「版本距离 → 来源序」,全不满足时选最接近要求的那个 (托管 25 与 JAVA_HOME/扫盘 17 之间选 17,而不是按 rank 选托管)。新增 `select::decide`: 不符且**没有人显式指定 Java** 时 `ull launch` 直接报 `java_mismatch` 不 spawn(`--java` / 实例 `javaPath` 是豁免,只告警)——1.12.2 配 Java 17/25 必然起不来,警告没有信息量。 `JavaMismatch` + `check` 拆到 `mismatch.rs` 并加 `advice()`(mapping.rs 408→282 行)。 D6:`LaunchSession::finish` 的等进程改成**有界**。判据在 `startup_watch.rs`(纯逻辑): ①窗口从未出现且**连续 N 秒没有任何日志**(还在打日志就说明还在加载,慢加载不被判死); ②日志出现关闭标记后 N 秒仍未退出(实机「关窗后 java.exe 仍存活」的形状)。 到点只**停止等待、绝不杀进程**:写 `session_end(still_running)` + 索引 + `launcher.log`, 返回 `LaunchError::Watchdog`,CLI 翻成 `launch_timeout`。两个时长可配 (默认 300s/60s;`ULL_LAUNCH_STARTUP_TIMEOUT_SECS` / `ULL_LAUNCH_SHUTDOWN_GRACE_SECS`, 生效值每次启动写进 launcher.log 与人读输出)。 D10:把「被终止」与「应用错误」分开。①我们自己杀的:`tree_kill` **送达即登记** `kill_registry`(pid 登记簿,取走语义、上限 64),覆盖 GUI 从别的线程 `kill_tree` 的路径, `finish` 据此判 `killed`;②外部强杀:Windows 上「退出码 1 + 零错误输出 + 无崩溃/JVM 关键字」 判 `killed` 并标 `terminated_externally`(任务管理器与 `taskkill /F` 都是 `TerminateProcess(h, 1)`,应用真崩给的是 NTSTATUS 异常码)。 顺带:`SessionHandle` 拆 `session_handle.rs`(launch_session.rs 422→343 行)、 `NativesReport::to_json` 落 core(cli/launch.rs 腾出空间,仍 399 行)。 用例:select 距离/取舍、startup_watch 状态机、watchdog_cases(4 条真进程)、 exit_cases(外部终止与「我们杀的」区分)、pipeline 跨线程 kill。
This commit is contained in:
1 parent
5959a27add
commit
ff78fe2cae
23 files changed
+1708
-250
No files matched your search
@@ -124,6 +124,19 @@ pub enum LaunchError {
|
||||
/// 底层错误。
|
||||
source: std::io::Error,
|
||||
},
|
||||
/// 看门狗到点**停止等待**(D6):进程仍在运行,我们只是不再等它了。
|
||||
Watchdog {
|
||||
/// 目标进程号(没有被结束)。
|
||||
pid: u32,
|
||||
/// 判据 id:`startup_timeout` / `shutdown_timeout`。
|
||||
reason: &'static str,
|
||||
/// 已经等了多久(毫秒)。
|
||||
waited_ms: u64,
|
||||
/// 判据上限(毫秒)。
|
||||
limit_ms: u64,
|
||||
/// 会话事件流(现场)。
|
||||
log_path: PathBuf,
|
||||
},
|
||||
}
|
||||
|
||||
impl fmt::Display for LaunchError {
|
||||
@@ -142,6 +155,28 @@ impl fmt::Display for LaunchError {
|
||||
Self::Kill { pid, source } => {
|
||||
write!(f, "结束进程树失败(pid {pid}):{source}")
|
||||
}
|
||||
Self::Watchdog {
|
||||
pid,
|
||||
reason,
|
||||
waited_ms,
|
||||
limit_ms,
|
||||
log_path,
|
||||
} => {
|
||||
let what = if *reason == "shutdown_timeout" {
|
||||
"游戏已开始关闭但一直没退出"
|
||||
} else {
|
||||
"启动后一直没有任何日志、也没出现游戏窗口"
|
||||
};
|
||||
write!(
|
||||
f,
|
||||
"{what}:等了 {:.0}s(上限 {:.0}s)就停止等待了。进程 {pid} 仍在运行、**没有被结束**\
|
||||
(可能只是加载得慢,也可能真卡住了);事件流见 {}。放宽上限:设环境变量 \
|
||||
ULL_LAUNCH_STARTUP_TIMEOUT_SECS / ULL_LAUNCH_SHUTDOWN_GRACE_SECS(秒,0 = 不限)",
|
||||
*waited_ms as f64 / 1000.0,
|
||||
*limit_ms as f64 / 1000.0,
|
||||
log_path.display()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -154,6 +189,7 @@ impl std::error::Error for LaunchError {
|
||||
Some(source)
|
||||
}
|
||||
Self::Session { .. } => None,
|
||||
Self::Watchdog { .. } => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user