Shell

互動式 shell 應該在孤立的程序組中做什麼?

  • March 22, 2013

(根據https://stackoverflow.com/questions/13718394/what-should-interactive-shells-do-in-orphaned-process-groups中的建議在 unix 中重新發布)

簡短的問題是,如果 shell 位於不擁有 tty 的孤立程序組中,它應該做什麼?但我建議閱讀長問題,因為它很有趣。

這是一種有趣且令人興奮的方法,可以使用您最喜歡的外殼將您的筆記型電腦變成攜帶式空間加熱器(除非您是那些 tcsh 怪人之一):

#include <unistd.h>   
int main(void) {
   if (fork() == 0) {
       execl("/bin/bash", "/bin/bash", NULL);
   }
   return 0;
}

這會導致 bash 將 CPU 固定在 100%。zsh 和 fish 也一樣,而 ksh 和 tcsh 咕噥著一些關於工作控制的事情,然後就倒下了,這有點好,但不多。哦,這是一個與平台無關的違規者:OS X 和 Linux 都受到影響。

我的(可能是錯誤的)解釋如下:子外殼檢測到它不在前台:tcgetpgrp(0) != getpgrp(). 因此它試圖停止自己:killpg(getpgrp(), SIGTTIN). 但是它的程序組是孤立的,因為它的父程序(C 程序)是領導者並且死了,並且SIGTTIN發送到孤立的程序組只是被丟棄(否則沒有什麼可以再次啟動它)。因此,子 shell 並沒有停止,但它仍然在後台,所以它會立即再次執行所有操作。沖洗並重複。

我的問題是,命令行 shell 如何檢測到這種情況,它應該做什麼?我有兩個解決方案,都不是理想的:

  1. 嘗試向 pid 與我們的組 ID 匹配的程序發出信號。如果失敗ESRCH,則意味著我們可能是孤兒。
  2. 嘗試從/dev/tty. 如果失敗EIO,則意味著我們可能是孤兒。

(我們跟踪的問題是https://github.com/fish-shell/fish-shell/issues/422

謝謝你的想法!

我同意你的分析,我同意聽起來你必須檢測你的程序組是否是孤立的。

tcsetattr如果程序組是孤立的,也意味著返回EIO(並且我們沒有阻止/忽略 SIGTT OU。這可能比read終端上的 a 侵入性更小。

請注意,您可以使用以下方法重現它:

(bash<&1 &)

您需要重定向,否則在後台執行命令時標準輸入將重定向到 /dev/null。

(bash<&1 & sleep 2)

給出更奇怪的行為,因為你最終會從終端讀取兩個 shell。他們忽略SIGTTIN並且新的沒有檢測到,一旦啟動它就不再在前台程序組中。

ksh93的解決方案還不錯:在放棄之前只能通過該循環最多 20 次(而不是無限次)。

引用自:https://unix.stackexchange.com/questions/59793