fix(core): 所有子进程统一走 platform::child::quiet + 角色守卫(M213)

GUI 父进程(PE Subsystem = 2)spawn 控制台子进程时,Windows 会为子进程新建一块
控制台——桌面上就是「黑框闪一下」。改前 crates/core/src 有 21 处 Command::new,
只有 tree_kill 那一处带了 CREATE_NO_WINDOW,于是探 N 个 JDK 就闪 N 次 java -version。

- 新增 crates/core/src/platform/child.rs:唯一构造器 quiet(program),Windows 上统一
  .creation_flags(CREATE_NO_WINDOW),其它平台原样返回。tree_kill 里那份就地合并进来,
  不再保留第二份常量。
- 20 处 spawn 全部改走它(region_system / java{discover,manual,probe,proc,termux} /
  addon exec / platform{linux_caps,macos_version,theme_probe,vk_probe,windows_version,
  wallpaper/io})。
- launch/process.rs 零改动:游戏进程要 CREATE_NEW_PROCESS_GROUP 撑 taskkill /T,
  带不带控制台窗口是产品决定。
- crates/core/tests/child_quiet.rs:按角色判「有没有绕开构造器」的守卫,外加构造器
  本身的 4 条行为用例。三条变异(裸 Command::new / 别名 Spawn::new / 删掉 creation_flags)
  都实测变红并已还原。
This commit is contained in:
AskaEth committed 2026-11-09 15:07:56 +08:00
1 parent bb8be87c8f
commit 40a296471d
17 files changed
+417 -39

No files matched your search

+6 -9
View File
@@ -28,7 +28,8 @@
//! 的实际停止流程以“进程是否真的消失”为准(`try_wait` 轮询),本模块只提供发送动作。
use std::io;
use std::process::Command;
use crate::platform::child::quiet;
/// 温和关闭(Windows 无 `/F`;POSIX `SIGTERM`)。
pub fn terminate(pid: u32) -> io::Result<()> {
@@ -100,7 +101,7 @@ fn pgid_of(pid: u32) -> Option<u32> {
#[cfg(all(unix, not(target_os = "linux")))]
fn pgid_of(pid: u32) -> Option<u32> {
let output = Command::new("ps")
let output = quiet("ps")
.args(["-o", "pgid=", "-p", &pid.to_string()])
.output()
.ok()?;
@@ -113,18 +114,14 @@ fn pgid_of(pid: u32) -> Option<u32> {
#[cfg(windows)]
mod imp {
use super::*;
use std::os::windows::process::CommandExt;
/// 不弹控制台窗口(否则 kill 子进程会闪一个黑框)。
const CREATE_NO_WINDOW: u32 = 0x0800_0000;
pub(super) fn signal(pid: u32, force: bool) -> io::Result<()> {
let mut command = Command::new("taskkill");
// `CREATE_NO_WINDOW` 由 `platform::child::quiet` 统一带(否则 kill 子进程会闪一个黑框)。
let mut command = quiet("taskkill");
command.arg("/PID").arg(pid.to_string()).arg("/T");
if force {
command.arg("/F");
}
command.creation_flags(CREATE_NO_WINDOW);
let status = command
.stdout(std::process::Stdio::null())
.stderr(std::process::Stdio::null())
@@ -168,7 +165,7 @@ mod imp {
/// `kill` 不存在时给**明确**错误而不是静默失败:否则调用方只会看到“进程仍在运行”,
/// 排查方向会被带偏(M48 之前的红灯就是这么来的)。
fn run_kill(flag: &str, args: &[&str]) -> io::Result<bool> {
match Command::new("kill")
match quiet("kill")
.arg(flag)
.args(args)
.stdout(std::process::Stdio::null())