2012-12-05 22 views
25

簡短的問題是,如果一個shell在一個不擁有tty的孤兒進程組中,那麼shell應該怎麼做?但我建議閱讀這個長問題,因爲它很有趣。交互式shell在孤立進程組中應該做些什麼?

這是一個有趣和令人興奮的方式把你的筆記本電腦變成一個便攜式空間加熱器,用你喜歡的外殼(除非你是其中的一個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則嘟something了一些關於工作控制的東西,然後龍捲了一下,這有點更好,但並不多。噢,它是一個平臺不可知的罪犯:OS X和Linux都受到影響。

我的(可能是錯誤的)解釋如下:子shell檢測到它不在前臺:tcgetpgrp(0) != getpgrp()。因此它試圖阻止自己:killpg(getpgrp(), SIGTTIN)。但是它的進程組是孤立的,因爲它的父進程(C程序)是領導者並且死了,並且發送給孤立進程組的SIGTTIN只是被放棄了(否則什麼都不能重新啓動)。因此,子shell不會停止,但它仍然在後臺,所以它馬上就會完成。沖洗並重復。

我的問題是,命令行shell如何檢測這種情況,以及它做什麼是正確的?我的想法是shell從stdin中嘗試read,並且只要讀取它就會退出EIO。

感謝您的想法!

編輯:我試着對/ dev/tty執行一個零長度的讀取(),並且成功了,這是不好的。爲了獲得EIO,我實際上必須準備從/ dev/tty讀取一些數據。

編輯:我的另一個想法是kill(getpgrp(), 0)。如果進程組是孤立的,那麼我相信這總是會失敗。然而,它也可能失敗,因爲我沒有權限向會議領導發信號。

編輯:對於任何人後來發現這個,我最終做的是在https://github.com/fish-shell/fish-shell/issues/422描述。另外,未來如何?

+5

便攜式空間加熱器備註+1。我笑了;) –

+2

將最好的套件http://unix.stackexchange.com/ – mtk

+1

@威爾如何不是一個編程問題? – Gilles

回答

3

這裏的strace的說是發生了什麼:

 
--- SIGTTIN (Stopped (tty input)) @ 0 (0) --- 
rt_sigaction(SIGTTIN, {SIG_IGN, [], SA_RESTORER, 0x7fd5f6989d80}, {SIG_DFL, [], SA_RESTORER, 0x7fd5f6989d80}, 8) = 0 
ioctl(255, TIOCGPGRP, [9954])   = 0 
rt_sigaction(SIGTTIN, {SIG_DFL, [], SA_RESTORER, 0x7fd5f6989d80}, {SIG_IGN, [], SA_RESTORER, 0x7fd5f6989d80}, 8) = 0 
kill(0, SIGTTIN)      = 0 
--- SIGTTIN (Stopped (tty input)) @ 0 (0) --- 
rt_sigaction(SIGTTIN, {SIG_IGN, [], SA_RESTORER, 0x7fd5f6989d80}, {SIG_DFL, [], SA_RESTORER, 0x7fd5f6989d80}, 8) = 0 
ioctl(255, TIOCGPGRP, [9954])   = 0 
rt_sigaction(SIGTTIN, {SIG_DFL, [], SA_RESTORER, 0x7fd5f6989d80}, {SIG_IGN, [], SA_RESTORER, 0x7fd5f6989d80}, 8) = 0 
kill(0, SIGTTIN)      = 0 
[repeat...] 

,這裏是爲什麼,從jobs.c,bash的4.2:

while ((terminal_pgrp = tcgetpgrp (shell_tty)) != -1) 
    { 
     if (shell_pgrp != terminal_pgrp) 
     { 
      SigHandler *ottin; 

      ottin = set_signal_handler(SIGTTIN, SIG_DFL); 
      kill (0, SIGTTIN); 
      set_signal_handler (SIGTTIN, ottin); 
      continue; 
     } 
     break; 
    } 

關於怎樣做它...嗯,這是超越我的能力。但是,我認爲這是有用的信息,並且有點評論。

相關問題