破管不再结束程序?

时间:2008-09-19 15:39:44

标签: linux shell tcsh broken-pipe

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

$> do_something_intensive | less

然后退出 less ,用于立即将您返回到SuSE8或以前版本的响应式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)

less 被杀死时

我可以肯定在我的程序中编写一个信号处理程序并确保它终止,但我更需要一些环境变量或shell选项来强制程序在SIGPIPE上终止

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

3 个答案:

答案 0 :(得分:8)

好吧,如果在读取器消失后尝试写入管道,则会生成SIGPIPE信号。应用程序能够捕获此信号,但如果没有,则该过程将被终止。

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

答案 1 :(得分:2)

是否“改变了某些事情”?

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

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

答案 2 :(得分:0)

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

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

哪个建议我的终端实际上是问题的根源......如果忽略了SIGPIPE,shell本身也会忽略SIGPIPE ......

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