Skip to content

收掉 AGENTS.md 的四項 follow-up,並修好 WHP 上 guest 輸出全黑的真因 - #134

Merged
TimLai666 merged 6 commits into
mainfrom
fix/follow-ups-liveness-teardown
Jul 28, 2026
Merged

收掉 AGENTS.md 的四項 follow-up,並修好 WHP 上 guest 輸出全黑的真因#134
TimLai666 merged 6 commits into
mainfrom
fix/follow-ups-liveness-teardown

Conversation

@TimLai666

Copy link
Copy Markdown
Owner

What

AGENTS.md 的四項 follow-up 做完,過程中在實體 Windows(WHP)抓到並修掉一個更嚴重的問題:guest userspace 的 stdout/stderr 完全到不了 host

Why / How

四項 follow-up:

Follow-up 處理
vz-smoke.sh 的 pkill 治標可升級為斷言 改成「10 秒內 chefer-vz-helper 必須消失,否則報 helper 變孤兒」
runtime 單發 SIGINT 下 helper 收攤有 ~5s 延遲 vmm-backend 新增行程級 liveness 登記簿,Ctrl-C handler 進來先關掉 helper 的 stdin 寫端
whp 防孤兒修復待實機驗證 實體 Windows 11 驗過:taskkill /F 殺 runtime 後 helper 0.5 秒內消失,零殘留
branch protection 的必要檢查名稱失效 已修 repo 設定(無後綴那條換成兩條帶 target 後綴的),PR 不必再 admin bypass

過程中另外修的兩件事:

  • .gitattributes 釘 LF:Windows checkout 的 core.autocrlf=true 會把 repo 內所有 .shscripts/appliance/init 轉成 CRLF。前者一進 WSL 就 set: pipefail: invalid option name;後者更嚴重——它會被原樣烤進 initramfs,#!/bin/busybox sh\r 等於 guest 開機直接壞掉。
  • WHP 的 8250 補上 THRE 中斷(本 PR 的重點):原本 serial.rs 的 IIR 永遠回 0x01、COM1 也沒接 PIC。kernel 的 printk console 走 polled write 所以沒事,但 Linux 的 8250 tty 送字是 interrupt-driven——start_tx 開 IER bit1 後就等 THRE 中斷才續傳,等不到就一個 byte 都送不出去。對 Windows-without-WSL 的使用者,等於所有 app 輸出都是黑的,且症狀偽裝成「服務沒起來」。

Testing

  • cargo test --workspace 全過;cargo fmtcargo clippy --workspace --all-targets 無告警
  • serial THRE 狀態機四條新測試(開啟中斷、送完再拉、遮罩時不拉、關閉後不拉),先寫測試確認失敗再實作
  • liveness 登記簿一條 unix 測試:用 cat 代打 helper,驗「關閉寫端 → 子行程收到 EOF 結束」
  • 實體 Windows 11(WHP)驗證:修前 console 只有 kernel/init 的 kmsg,修後 [guest-agent] service 'web' started[web] … 正常出現;埠轉發 curl 127.0.0.1:18080ok;殺 runtime 後 helper 無殘留

Notes

WHP 的 guest console 沒有自動化端到端保護——QEMU E2E 走 virtio-console/hvc0 覆蓋不到,GitHub 的 windows runner 也開不了巢狀虛擬化。目前靠 serial.rs 的單元測試鎖狀態機,端到端只能實機驗。已留成新的 follow-up。

macOS 側(vz)的改動本機無法編譯驗證,靠 CI 的 macos build 把關;vz-smoke.sh 的新斷言要等下次在真 Mac 上跑。

vmm-backend 新增行程級 liveness 登記簿(hold_liveness_handle /
close_liveness_handles),vz、whp 兩個後端的 helper stdin 寫端改為交它保管
(語意等同原本的 mem::forget:handle 隨行程存亡)。runtime 的 Ctrl-C handler
進來第一件事就關掉它,helper 立刻讀到 EOF 自我了結、run_app 立刻返回,不必等
5 秒寬限跑完 exit(130)(實測單發 SIGINT 原本約 6 秒才收攤)。

有 terminal/both 服務時不登記——寫端在 stdin 泵送執行緒手上,訊號路徑關它會
與 write 競爭 fd;那種 app 跑在終端機裡,Ctrl-C 走 process group 沒這問題。

同時把 vz-smoke.sh 收尾的 pkill 治標改成斷言:等 10 秒內 chefer-vz-helper 必須
消失,否則報「helper 變孤兒」——實機一鍵驗證直接覆蓋 stdin-EOF 這條修復。

AGENTS.md 的 follow-ups 收掉四項(vz-smoke 斷言、SIGINT 收攤延遲、whp 防孤兒
實機驗證、branch protection 檢查名稱),新增一項實機觀察待查。
Windows checkout 的 core.autocrlf=true 會把 working tree 全轉成 CRLF,導致
repo 內所有 .sh 在 WSL/Linux 下一跑就 `set: pipefail: invalid option name`
(CRLF 讓 bash 當成 sh 語法錯誤),而 scripts/appliance/init 更嚴重——它會被
原樣烤進 initramfs,`#!/bin/busybox sh\r` 等於 guest 開機直接壞掉。

加 .gitattributes 明確釘 LF,與 CI(Linux runner)及 release 產物一致。
實機驗證翻案:服務其實正常啟動、埠轉發也通,看不到輸出是 whp-helper 的 serial
模擬 IIR 永遠回 no-pending、COM1 沒接 PIC,Linux 8250 tty 的 interrupt-driven TX
因此一個 byte 都送不出去;只有 kernel printk 的 polled console write 到得了 host。
實體 Windows 11 抓到:WHP 上跑 app,console 只看得到 kernel 與 init 的 kmsg
訊息,服務輸出全黑,看起來像服務起不來。實際上服務跑得好好的(埠轉發 curl 通、
把 init 輸出導進 /dev/kmsg 就看得到 guest-agent 全部日誌)。

真因:serial.rs 的 IIR 永遠回 0x01(no pending interrupt),COM1 也沒接 PIC。
kernel 的 printk console 走 polled write 所以沒事,但 Linux 的 8250 tty 送字是
interrupt-driven——start_tx 開 IER bit1 之後就等 THRE 中斷才續傳,等不到就一個
byte 都送不出去。

修法照真硬體語意:寫 IER 開 THRI 或寫完 THR 就把 thre_pending 立起來(本模擬的
TX 即時完成),IO exit 後對 PIC 拉 IRQ 4,guest 讀 IIR 得 0x02 並認掉。Linux 沒
東西可送時會自己清掉 THRI(__stop_tx),所以不會變成中斷風暴——四條單元測試把
這個狀態機鎖住。

實機驗證(同一個 bundle,修前修後):修後 `[guest-agent] service 'web' started`、
`[web] WHP_NC_SERVICE_UP` 皆正常出現,埠轉發與防孤兒行為不受影響。
…r 豁免

CI 的 -D warnings 擋下來的:只有 vz(macOS)與 whp(Windows)會登記 helper 的
liveness 寫端,Linux 的 namespaces 後端是 in-process 呼叫 guest-agent、沒有 helper
行程,該平台只有單元測試用得到這個函式。比照本檔既有的 wsl_util/vz_util 慣例豁免。
workspace 建置與 CI 都正常,只有指定 -p 時 windows-sys 的 feature 聯集不同,
whp.rs 找不到 CreateJobObjectW。影響 AGENTS.md Commands 節寫的單 crate 測試用法。
@TimLai666
TimLai666 merged commit ce168a7 into main Jul 28, 2026
18 checks passed
@TimLai666
TimLai666 deleted the fix/follow-ups-liveness-teardown branch July 28, 2026 09:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant