v0.18.10:讓「同步引擎沒在跑」說出死因(leo Windows 實測①②的診斷前置)
leo 08-06 Windows 回報:「一直在『看守中』和『沒有在跑』中間閃,要我重啟但重啟無效, 我覺得它在跑個迴圈不停重複」+「加一個資料夾明顯沒產生看守資料夾」。 朋友的一般 PC(非 ARM)也一樣,停在等待中 ⇒ **不是 ARM 模擬的問題,是 Windows 通用**。 ## 已定位的機制(不是根因,是「為什麼查不出根因」) 閃爍=子行程一啟動就死 → supervisor 退避重拉 → 狀態在 Starting(alive=true)與 Error(false)之間彈跳 ⇒ 畫面跟著閃。而**死因一直被記在 Status().LastError 裡, 從來沒有上過畫面、也沒寫進 app.log** ⇒ 使用者只看到閃爍與「請重新開啟」, 重開當然無效(死因沒變)。這是「安靜地略過」的同一種病換地方發作。 ## 這版做的 - 死因上畫面:重試 >= 3 次改顯示「同步引擎一直啟動失敗,已自動重試 N 次|原因:…」, 且**黏住不閃**(不受重起過程中的 Starting 影響) - 每次異常結束寫進 app.log(同錯誤 10 次內只記一次,避免洗爆) ## 排除掉的嫌疑(查過,不是) - PDF 引擎(pdfium/wasm):**延遲初始化**,第一次讀 PDF 才啟動 ⇒ 不會在啟動時炸 - ARM 模擬:leo 朋友的一般 x64 PC 同樣症狀 - 待查嫌疑:Wails 的 Windows 版是 `-H windowsgui`(GUI subsystem,無主控台), 而 v0.18.8 的 collector.exe 是 `go build` 的 console subsystem—— v0.18.9 合併成單一 binary 後,子行程換成 GUI subsystem 的自己。**尚未證實。** ## 順帶修好自己的閘(它擋對了我) 指紋閘擋下「v0.18.10 已對應另一份原始碼」——因為第一次打包失敗、版號卻已被戳。 ⇒ 加判準:**磁碟上沒有該版號產物=從未出貨,允許重戳**(不用去手改 JSON, 那種爛示範遲早被改成「都放行」)。 ## 安裝程式(leo ③)尚未兌現,誠實記錄 `wails build -nsis` 需要 makensis;Homebrew 的 3.12 在這台 macOS **連兩行的最小腳本 都在寫檔階段丟 std::bad_alloc**,zlib/bzip2/lzma 三壓縮器全崩,brew extract 舊版 被 homebrew/core 擋。且帶 -nsis 會讓 wails 整個中止、連 exe 都不產 ⇒ build-win.sh 改成**先煙霧測試 makensis**,壞的就只出裸 exe 並大聲警告。
This commit is contained in:
@@ -64,6 +64,23 @@ func startSupervisor() {
|
||||
}
|
||||
sup = supervisor.New(bin, cfg)
|
||||
sup.ArgPrefix = collectorArgPrefix() // 同一支執行檔,換身分跑
|
||||
// 🔴 2026-08-06:每次狀態變成 Error 都寫進 app.log。
|
||||
// 沒有這一段,「子行程一啟動就死」在檔案裡**一個字都沒有**——
|
||||
// leo 在 Windows ARM 撞到時,畫面只有閃爍、log 只有「同步引擎已啟動」,
|
||||
// 死因(Status().LastError)只活在記憶體裡,跟著程式一起消失。
|
||||
// 只在錯誤訊息**變了**或每 10 次才記一次,避免重試迴圈把 log 洗爆。
|
||||
var lastLogged string
|
||||
var lastN int
|
||||
sup.SetOnChange(func(st supervisor.Status) {
|
||||
if st.State != supervisor.StateError {
|
||||
return
|
||||
}
|
||||
if st.LastError == lastLogged && st.Restarts-lastN < 10 {
|
||||
return
|
||||
}
|
||||
lastLogged, lastN = st.LastError, st.Restarts
|
||||
appLog("同步引擎異常結束(第 %d 次重試):%s", st.Restarts, st.LastError)
|
||||
})
|
||||
sup.Start()
|
||||
appLog("同步引擎已啟動:%s", bin)
|
||||
}
|
||||
@@ -146,6 +163,30 @@ func installSignalHandler() {
|
||||
// 這不是第三種判斷法——db17f28(08-05)已為「同步中」立下同一條路:
|
||||
// 「改讀 sup.Status().State ⇒ **接回既有機制,不發明第三種判斷法**」。
|
||||
// 當時只改了 collectorSyncing 那半邊,這裡是把漏掉的另一半補上。
|
||||
//
|
||||
// collectorFailure 回報「同步引擎是不是一直啟動失敗」,以及死因。
|
||||
//
|
||||
// 🔴 2026-08-06 leo 在 Windows 11 ARM 實測:畫面「一直在『看守中』和『沒有在跑』
|
||||
//
|
||||
// 中間閃…我覺得它在跑個迴圈不停重複」。
|
||||
// 真相就是那樣——子行程一啟動就死,supervisor 退避後再拉,狀態在
|
||||
// Starting(collectorAlive=true)與 Error(false)之間彈跳 ⇒ 畫面跟著閃。
|
||||
// **而死因一直被記在 Status().LastError 裡,從來沒有上過畫面**
|
||||
// ⇒ 使用者只看到閃爍與「請重新開啟」,重開當然無效(死因沒變)。
|
||||
// 這是「安靜地略過」的同一種病,換一個地方發作。
|
||||
//
|
||||
// restarts 達到門檻才算「一直失敗」——偶爾重起一次是正常的(例如換設定)。
|
||||
func collectorFailure() (msg string, restarts int, looping bool) {
|
||||
if sup == nil {
|
||||
return "", 0, false
|
||||
}
|
||||
st := sup.Status()
|
||||
return st.LastError, st.Restarts, st.Restarts >= crashLoopThreshold
|
||||
}
|
||||
|
||||
// crashLoopThreshold=重起幾次算「一直失敗」。3 次以內可能只是換設定或暫時性錯誤。
|
||||
const crashLoopThreshold = 3
|
||||
|
||||
func collectorAlive() bool {
|
||||
if sup == nil {
|
||||
return false
|
||||
|
||||
Reference in New Issue
Block a user