5

当您管道两个进程并在管道的“输出”处终止一个进程时,第一个进程用于接收“Broken Pipe”信号,这通常也会终止它。例如跑步

$> do_something_intensive | less

然后在 SuSE8 或更早版本上退出less used 以立即将您返回到响应式 shell。当我今天尝试这样做时,do_something_intensive显然仍在运行,直到我手动将其杀死。似乎有些东西发生了变化(glib?shell?),使程序忽略“破管道”......

你们中有人对此有提示吗?如何恢复以前的行为?为什么它被改变了(或者为什么它总是存在多种语义)?

编辑:进一步的测试(使用 strace)显示生成了“SIGPIPE” ,但程序没有中断。一个简单的

#include <stdio.h>
int main() 
{
   while(1) printf("dumb test\n");
   exit(0);
}

将永无止境地继续下去

--- SIGPIPE (Broken pipe) @ 0 (0) ---
write(1, "dumb test\ndumb test\ndumb test\ndu"..., 1024) = -1 EPIPE (Broken pipe)

更少被杀死时。我可以肯定地在我的程序中编写一个信号处理程序并确保它终止,但我更多的是寻找一些环境变量或 shell 选项来强制程序在 SIGPIPE 上终止

再次编辑:这似乎是一个特定于 tcsh 的问题(bash 正确处理它)并且依赖于终端(Eterm 0.9.4)

4

3 回答 3

8

好吧,如果在阅读器离开后尝试写入管道,则会生成 SIGPIPE 信号。应用程序有能力捕捉到这个信号,但如果没有,进程就会被杀死。

在调用进程尝试写入之前不会生成 SIGPIPE,因此如果没有更多输出,则不会生成它。

于 2008-09-19T15:45:12.820 回答
2

“做一些密集的事情”有没有改变?

正如丹尼尔所提到的,SIGPIPE 不是一个神奇的“你的管道消失了”信号,而是一个“不错的尝试,你不能再读/写那个管道”信号。

如果您可以控制“做一些密集的事情”,您可以更改它以在它旋转时写出一些“进度指示器”输出。这将及时提高 SIGPIPE。

于 2008-09-19T16:26:02.393 回答
0

感谢您的建议,解决方案越来越接近......

根据 tcsh 的手册页,“非登录 shell 从其父级继承终止行为。其他信号具有 shell 从其父级继承的值。”

这表明我的终端实际上​​是问题的根源......如果它忽略了 SIGPIPE,shell 本身也会忽略 SIGPIPE......

编辑:我有明确的确认问题只出现在 Eterm+tcsh 中,并且在 Eterm 源代码中发现了一个可疑的缺失信号(SIGPIPE,SIG_DFL)。我认为结案。

于 2008-09-23T15:50:35.503 回答