我在代码中使用czmq
和zmq
个库。我通过调用main中的SIGINT
为signal
注册了一个信号处理程序。代码如下所示:
#include "czmq.h"
void sig_int(int signal);
void* pub_handler(){
zctx_t *context = zctx_new ();
void *publisher = zsocket_new (context, ZMQ_PUB);
zsocket_connect (publisher, "tcp://localhost:5555");
sleep(1);
char topic[20] = "REQ: speedlimit";
// while (true)
{
sleep( randof(10) );
zstr_sendm (publisher, topic);
zstr_send (publisher, "driver analysis data");
}
zctx_destroy (&context);
}
void* sub_handler(){
zctx_t *context = zctx_new();
void *subscriber = zsocket_new (context, ZMQ_SUB);
zsocket_connect (subscriber, "tcp://localhost:5557");
srandom ((unsigned) time (NULL));
char subscription [20] = "RESP: speedlimit" ;
zsocket_set_subscribe (subscriber, subscription);
while (true) {
char *topic = zstr_recv (subscriber);
if(!topic)
break;
char *data = zstr_recv (subscriber);
assert (streq (topic, subscription));
puts (topic);
puts (data);
free (topic);
free (data);
}
zctx_destroy (&context);
}
int main(int argc, const char *argv[])
{
pthread_t pub_id, sub_id;
signal (SIGINT, sig_int);
pthread_create(&pub_id, NULL, pub_handler, NULL);
pthread_create(&sub_id, NULL, sub_handler, NULL);
pthread_join(pub_id, NULL);
pthread_join(sub_id, NULL);
return 0;
}
void sig_int(int signal){
printf (" Interrupted\n");
exit(0);
}
编译为gcc -o app app.c -lpthread -lczmq -lzmq
。
当给出ctrl+c
中断时,上面的代码不会进入信号处理程序。
czmq
或zmq
库有什么问题?应该如何处理?
答案 0 :(得分:6)
documentation for zctx表示zctx
为SIGINT
和SIGTERM
设置了自己的信号处理程序,可能会覆盖您的信号处理程序。
设置信号(SIGINT和SIGTERM)处理,以便阻止调用 例如zmq_recv()和zmq_poll()将在用户按下时返回 CTRL-C
它还说zctx
已被弃用,而不是zsock
,根据其文档,它似乎没有设置信号处理程序。所以我的第一个建议是使用新的zsock
套接字API。
但是,在这两种情况下,您似乎也可以调用zsys_handler_set(NULL);
(记录here)来显式禁用CZMQ中的默认SIGINT / SIGTERM处理。
PS:printf
不是异步信号安全的,这意味着它不应该用在信号处理程序中。有关POSIX中异步信号安全功能的列表,请参阅here。
答案 1 :(得分:4)
在zmq mailing list
!!
Pieter Hintjens说':: strong> CZMQ
确实设置了自己的信号处理来捕获SIGINT和SIGTERM。
您可以通过调用
zsys_handler_set (NULL);
在我的代码中添加上面的行禁用了czmq设置的信号处理程序,现在我可以使用自己的信号处理程序了。
感谢Pieter Hintjens。
答案 2 :(得分:3)
答案 3 :(得分:1)
我认为您的问题与CZMQ无关,而且是由您的线程引起的。具体来说,主线程正在捕获信号,而子线程则没有。这是一个常见的陷阱。
有几种解决方案。我可能做的就是在主线程中休眠/等待(例如,你可以使用zmq_poll),然后当你收到信号时,告诉孩子线程结束。
一些评论......如果你打算使用CZMQ,那么为什么不使用它的线程设置,它将pthreads包装在一个更好的界面中。你有旧的zthread类和更新的zactor类。
答案 4 :(得分:0)
我认为你的主要计划应该还活着。试试这个 -
int main(int argc, const char *argv[])
{
pthread_t pub_id, sub_id;
signal (SIGINT, sig_int);
pthread_create(&pub_id, NULL, pub_handler, NULL);
pthread_create(&sub_id, NULL, sub_handler, NULL);
pthread_join(pub_id, NULL);
pthread_join(sub_id, NULL);
while(1); // Fix
}
您已使用signal
功能更改了信号表。
signal (SIGINT, sig_int);
因此,只要您发出SIGINT
信号(ctrl + c),它就会调用sig_int
函数。那是你的信号处理程序。但是在这个功能中你不会杀死任何进程。
因此,只要您按ctrl + c
,您的程序就会调用sig_int
函数,该函数将为每Interrupted
个信号打印SIGINT
。
如果您需要在按ctrl+c
时终止程序,请不要像下面那样修改信号表。
signal (SIGINT, sig_int);
而不是那个
signal (SIGINT, SIG_DFL);
当您按ctrl+c
时,它将终止您的计划。
否则你也可以试试这个 -
void sig_int(int signal){
signal (SIGINT, SIG_DFL); // here i am again changing the signal table to default.
printf (" Interrupted\n");
exit(0);
}
在这种情况下,当您第一次按ctrl+c
时,它会调用sig_int
功能,但是当您按第二次时它会终止您的程序。因为我修改了sig_int
函数中的信号表。