繁体   English   中英

使用信号和sigpipe

[英]Using signals and sigpipe

我正在进行一项任务,包括使用fork(进程),信号和选择编写程序来处理数据(计算pi)。

我现在正在处理信号,我认为我想要做的是使用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并使其再次写入管道?

谢谢!

通常,不是捕获SIGPIPE ,而是忽略它,这会导致write失败并使用EPIPE而不是静默终止程序。

但是:如果您在写入管道时收到SIGPIPE ,请不要再试一次。 它永远不会奏效。 SIGPIPE意味着管道没有读卡器 - 如果管道现在没有读卡器,它将永远不会有读卡器。 (想一想:没有读者的管子怎么会得到一个?这是不可能的!)

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

编辑:这里有两个问题要回答。 如果您无法回答这两个问题,那么请不要费心处理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");
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM