交互式shell在孤立进程组中应该做什么?

时间:2012-12-05 07:36:09

标签: shell unix signals process-group

简短的问题是,如果shell处于不拥有tty的孤立进程组中,它应该怎么办?但我建议阅读这个长问题因为它很有趣。

这是一种有趣且令人兴奋的方式,可以将您的笔记本电脑变成便携式空间加热器,使用您最喜爱的外壳(除非您是其中一个tcsh怪人):

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

这会导致bash将CPU固定在100%。 zsh和鱼做同样的事情,而ksh和tcsh笨拙地谈论工作控制,然后龙骨,这有点好,但不多。哦,这是一个与平台无关的罪犯:OS X和Linux都受到影响。

我的(可能是错误的)解释如下:子shell检测到它不在前台:tcgetpgrp(0) != getpgrp()。因此它试图阻止自己:killpg(getpgrp(), SIGTTIN)。但它的进程组是孤立的,因为它的父进程(C程序)是领导者并且死了,并且发送给孤立进程组的SIGTTIN刚刚被删除(否则什么都不能再启动它)。因此,子shell不会停止,但它仍然在后台,所以它会立即再次完成。冲洗并重复。

我的问题是,命令行shell如何检测这种情况,以及它做什么是正确的?我的想法是shell从stdin尝试read,如果read给它EIO就退出。

感谢您的想法!

编辑:我尝试在/ dev / tty上执行零长度读取(),并且成功,这很糟糕。为了获得EIO,我实际上必须准备从/ dev / tty中读取一些数据。

编辑:我的另一个想法是kill(getpgrp(), 0)。如果进程组是孤立的,那么我相信这将永远失败。但是,它也可能失败,因为我无权向会议负责人发出信号。

编辑:对于后来发现这一点的人来说,我最终要做的就是https://github.com/fish-shell/fish-shell/issues/422所描述的。还有,未来怎么样?

1 个答案:

答案 0 :(得分: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;
    } 

关于如何处理......这超出了我的能力范围。但是,我认为这是有用的信息,而且有点评论。