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

标签 shell unix signals process-group

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

这是一种有趣且令人兴奋的方法,可以使用您最喜欢的 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 嘟囔着一些关于工作控制的东西,然后倒过来,这要好一点,但不多。哦,这是一个平台不可知的罪犯:OS X 和 Linux 都受到影响。

我的(可能是错误的)解释如下:子 shell 检测到它不在前台:tcgetpgrp(0) != getpgrp() .因此它试图停止自己:killpg(getpgrp(), SIGTTIN) .但是它的进程组是孤立的,因为它的父进程(C 程序)是领导者并且死了,发送到孤立进程组的 SIGTTIN 只是被丢弃了(否则没有什么可以重新启动它)。因此,子 shell 并未停止,但它仍在后台,因此它会立即再次执行所有操作。冲洗并重复。

我的问题是,命令行 shell 如何检测这种情况,它应该做什么?我的想法是 shell 试图 read来自标准输入,如果 read 给它 EIO,则退出。

谢谢你的想法!

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

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

编辑:对于稍后发现此问题的任何人,我最终所做的描述在 https://github.com/fish-shell/fish-shell/issues/422 .还有, future 如何?

最佳答案

以下是 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...]

and here is why, from 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;
    } 

关于如何处理它......好吧,这超出了我的能力。但是,我认为这是有用的信息,对于评论来说有点多。

关于shell - 交互式 shell 在孤立进程组中应该做什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13718394/

相关文章:

linux - Bash/Shell 脚本中的安全输入验证

linux - 在编译时上传存储库

regex - 当扩展正则表达式 (ERE) 选项与 sed 一起使用时,为什么美元不匹配文字美元?

linux - 应该使用哪个 shell 以获得 Linux/MacOS/UNIX 最佳兼容性?

bash - 如何在文本文件中扩展 shell 变量?

c++ - Qt 信号和槽传递数据

c++ - gettimeofday 异步信号安全吗?如果在信号处理程序中使用它会导致死锁吗?

python - 确保带有子进程的 Python 脚本在 SIGINT 上死掉

linux - 提取大括号之间的文本

c - 为什么我不能忽略 SIGSEGV 信号?