Sidecar 生命周期管理¶
Tauri Rust shell 负责拉起 / 监控 / 重启 sidecar。这一层是用户体感 "OmicOS 起得来"的关键。
Sidecar spawn¶
src-tauri/src/lib.rs
里 setup hook 中:
let sidecar = app.shell().sidecar("omicos")?
.args(["--port", "0"])
.spawn()?;
binary 文件来自 src-tauri/binaries/omicos-<target>——构建前必须
拷过来(第一次构建)。
端口发现¶
sidecar 不接受 --port 直接绑——它选随机端口避冲突,把
pid\nport\n 写到 <workspace>/.omicos/serve.pid。
Tauri shell 启动后开始轮询 serve.pid 文件:
读到 → 解析端口 → push 到 SPA 的 store(通过 Tauri event)
SPA 拿到端口才能连 sidecar
stderr ring buffer¶
sidecar 的 stderr 流被 Tauri shell 读到,保留最近 30 行用于致命
错误时附在 kernel-fatal-error event 里。这样 SPA 弹的 confirm 框
能给用户看具体错误。
自动重启¶
CommandEvent::Terminated 触发后:
if state.child.is_some() {
sleep(Duration::from_millis(800)).await;
spawn_sidecar(...).await?;
}
state.child 在用户主动关窗时会被清空,所以正常关闭不会无限循环
重启。
致命错误分类¶
读最近 30 行 stderr,按关键字分类成:
kind |
触发条件 |
|---|---|
|
同 workspace 已经有另一个 sidecar 跑 |
|
工作区无写权限 |
|
端口被占(罕见——sidecar 自己选随机口) |
|
上面都不匹配 |
emit kernel-fatal-error: {kind, title, raw_stderr, exit_code} 给 SPA。
主窗 close 才杀 sidecar¶
app.on_window_event(|window, event| {
if let WindowEvent::CloseRequested { .. } = event {
if window.label() == "main" {
kill_sidecar();
}
// 子窗(auto-key 等)忽略
}
});
PR #104 + #105 修的"sidecar 莫名其妙挂"问题就是这里——以前没区分 窗口 label。
进一步¶
Pinia stores — 端口怎么传到 SPA