發表文章

目前顯示的是 三月, 2014的文章

Ctrl+C 運作的原理以及 session, terminal 和 process group

簡短版說明前陣子遇到一個神祕的問題: 執行程式 P 的時候, 可以用 ^C 中止它。但透過 shell script S 執行 P (S 內只有該程式名稱和參數而已), 就無法用 ^C 中止它。^\ 也是一樣情況, 不過 ^Z 可以正常 suspend。 檢查其它的環境因素發現: kill -INT PID 可以中止 P, 表示程式沒有攔截 SIGINT。 stty -a -F TTY_DEVICE 顯示 intr = ^C 且 isig, 表示輸入 ^C 後會被轉譯成 SIGINT。按 ^C 後螢幕上有顯示 ^C。 綜合以上的資訊, 無法理解還有什麼原因會讓 ^C 轉送 SIGINT 失效。 卡了一陣子後, 回頭翻 TLPI ch34 Process Groups, Sessions, and Job Control 以及 ch62 Teriminals 才找到答案。 答案是: P 有用 setpgid() 產生新的 process group, 於是 P 就不是 terminal foreground process group, 而 ^C 只會送給 terminal foreground process group。 詳細說明在沒有透過 shell script 執行 P 的情況, P 會自成一個新的 process group, 同時也是 terminal foreground process group (這是 shell fork process 後設定的)。之後即使程式有呼叫 setpgid(), 也不會改變 pgid, 因為 P 本來就是自己 process group leader。這時, P 仍然是 terminal foreground process group, 收得到傳給 terminal 的 ^C。 另一方面, 透過 shell script S 執行的情況, S 自成一個新的 process group 也會是 terminal foreground process group (同樣的, 是 shell 設定的)。S 執行 P, P 又用 setpgid() 自己成立一個新的 process group, 這個新的 process group 不是 terminal foreground process group, 也…