我有一个多线程服务器进程,用 C/C++ 编写,我正在尝试使用 Google perftools 进行分析。但是,当我使用 perftools 运行该进程时,我的服务器很快就会停止并出现“系统调用中断”错误,我认为这是由传入的 SIGPROF 引起的。(被中断的实际系统调用在我对zmq_recv的调用中很深,但我认为它是哪一个并不重要。)
这是预期的行为吗?我应该以某种方式明确处理这种情况吗?或者这里出了什么问题?
从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!)。