7

我有一个多线程服务器进程,用 C/C++ 编写,我正在尝试使用 Google perftools 进行分析。但是,当我使用 perftools 运行该进程时,我的服务器很快就会停止并出现“系统调用中断”错误,我认为这是由传入的 SIGPROF 引起的。(被中断的实际系统调用在我对zmq_recv的调用中很深,但我认为它是哪一个并不重要。)

这是预期的行为吗?我应该以某种方式明确处理这种情况吗?或者这里出了什么问题?

4

1 回答 1

8

zmq_recv()的 zeroMQ 文档中,我们可以预期EINTR如果在进行中接收到信号,它会返回。

在通话过程中生成信号zmq_recv()对于任何测试来说都是一项艰巨的任务。幸运的是,生成大量s 的gperftoolsSIGPROF已经在您的代码中发现了这个微妙的“错误”。

必须在您的代码中优雅地处理,因为 zeroMQ 框架正在优雅地放弃控制。重试逻辑可以像修改现有调用一样简单:

    /* Block until a message is available to be received from socket */
    rc = zmq_recv (socket, &part, 0);

使用新的(带有重试逻辑)如下:

   /* Block until a message is available to be received from socket
    * Keep retrying if interrupted by any signal
    */
    do {
        rc = zmq_recv (socket, &part, 0);
    } while(errno == EINTR);

还要在你的程序中安装一个信号处理函数。可以简单地忽略由于中断而导致的中断SIGPROF并继续重试。

最后,您可能想要处理特定的信号并采取相应的行动。例如,即使用户在您的程序正在等待时按下CTRL+ ,也可以优雅地终止您的程序。Czmq_recv()

   /* Block until a message is available to be received from socket
    * If interrupted by any signal,
    * - in handler-code: Check for signal number and update status accordingly.
    * - in regular-code: Check for status and retry/exit as appropriate
    */

    do {
        rc = zmq_recv (socket, &part, 0);
    } while(errno == EINTR && status == RETRY);

为了保持代码“干净”,使用上面的代码片段编写自己的static inline函数包装器会更好地为您服务zmq_recv(),您可以在程序中调用它。

关于在接收到信号后做出zmq_recv()返回的决定EINTR,您可能想查看这篇文章,该文章讨论了这种设计背后的更坏就是更好的理念,从实现的角度来看,这种设计更简单。


更新zmq_recv():在git.lucina.net/zeromq-examples.git/tree/zmq-camera.c中提供了处理信号的文档化代码。它与上面解释的路线相同,但它看起来经过了很好的测试,并且可以随时使用,并且可以使用大量详细的注释(yayyy zeromq!)。

于 2013-07-17T08:17:50.917 回答