简短的问题是,如果 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 如何检测到这种情况,它应该做什么?我的想法是外壳尝试read
从标准输入,如果读取给它 EIO 就退出。
谢谢你的想法!
编辑:我尝试在 /dev/tty 上执行零长度读取(),并且成功了,这很糟糕。为了获得 EIO,我实际上必须准备从 /dev/tty 读取一些数据。
编辑:我的另一个想法是kill(getpgrp(), 0)
。如果进程组是孤立的,那么我相信这将永远失败。但是,它也可能会失败,因为我无权向会话负责人发出信号。
编辑:对于以后发现此问题的任何人,我最终所做的都在https://github.com/fish-shell/fish-shell/issues/422中进行了描述。还有,未来怎么样?