2011-10-14 30 views
3

我正在处理一个任务,涉及编写程序来处理数据(计算pi)使用叉(进程),信号和选择。使用信号和sigpipe

我正在处理信号,我想我要做的就是使用SIGPIPE,所以如果程序捕获它,它会尝试再次写入管道(如果一个进程试图写入管道没有读者,它会发送SIGPIPE)。

我在main()中使用fork()通过将每个进程发送给worker函数来为每个进程分配相同的工作。

void worker(int id) { 
    .... (this piece of code is not relevant) 

    if(write(pfd[id][1], &c, sizeof(c)) == -1) 
     printf("Error occurred: %s\n",strerror(errno)); 

} 

我如何能实现信号在该功能捕捉SIGPIPE,并把它写入管道再次?

谢谢!

+0

你应该回去接受你提出的问题的答案。人们不可能回答你的问题,因为你不接受他们的答案。 –

+0

哦对不起!我会去做。编辑:完成!我是新来这个网站,它是如何工作,但我现在得到它:) – andrepcg

回答

9

通常,而不是捕获SIGPIPE忽略它,这会导致writeEPIPE一起失败,而不是以静默方式终止您的程序。

但是:如果您在写入管道时遇到了SIGPIPE,请不要再尝试。它永远不会工作。 SIGPIPE意味着管道没有读卡器 - 如果管道现在没有读卡器,它将永远不会有读卡器。 (想想这样:没有阅读器的管道将如何得到一个?这是不可能的!)

你的问题是,你正在关闭管道的另一端。解决这个问题,不用担心SIGPIPESIGPIPE只是症状。

编辑:这里有两个问题需要回答。如果您不能回答这两个这些问题,那么请不要打扰处理SIGPIPE

  1. 什么会导致我的程序来接收SIGPIPE接受SIGPIPE的唯一方法是让管道的阅读结束。如果读取过程崩溃,或者编程为关闭管道,则会发生这种情况。如果您正在编写网络服务器,或者与未知进程通信,这可能很常见。但是,如果你编写两个程序,都在本地运行,那么它可能表示编程错误。

  2. 当我的程序捕获到SIGPIPE时,我的程序会做什么?如果您正在编写使用管道与服务器通信的客户端进程,那么您应该怎么处理SIGPIPE?您不能再试一次,并且客户端通常无法重新启动他们连接的服务器。只要做明智的,默认的事情,并让SIGPIPE终止你的程序。但是,如果服务器正在将数据发送到它控制的客户端并获得SIGPIPE,那么可能会重新启动客户端。但是这可能是一个非常糟糕的主意 - 例如,如果客户端是确定性的,它将会再次崩溃,最终会导致无限循环而不是简单的崩溃。

所以这里的一般准则是:“只有抓住你准备来处理错误。”不要捕捉错误只是为了完整起见。只要让他们崩溃你的程序,或者导致操作失败,以后可以返回并调试它。

代码片段:这是我的一个项目的代码片段。如果你运行它,SIGPIPE不会终止你的过程。相反,write将生成EPIPE错误。如果您正在编写网络服务器,则EPIPE是客户端可能突然断开连接的一种可能方式。

void 
ignore_sigpipe(void) 
{ 
    struct sigaction act; 
    int r; 
    memset(&act, 0, sizeof(act)); 
    act.sa_handler = SIG_IGN; 
    act.sa_flags = SA_RESTART; 
    r = sigaction(SIGPIPE, &act, NULL); 
    if (r) 
     err(1, "sigaction"); 
} 
+0

我的程序工作正常,我没有得到任何错误(甚至没有SIGPIPE)。我在想“如果我得到SIGPIPE” – andrepcg

+0

如果你没有获得SIGPIPE,那你为什么需要处理它? –

+0

我不知道,但如果该程序将分配给很多计算机,其中一个获得SIGPIPE,我将通过防止这些情况成为一名优秀的程序员。那就是我所想的。如果我不对,那么告诉我:) – andrepcg