[英]signal handler not working
我在我的代碼中使用czmq
和zmq
庫。 我已經注冊了一個信號處理程序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
庫有什么問題以及應該如何處理?
zctx的文檔說zctx
為SIGINT
和SIGTERM
設置了自己的信號處理程序,可能會覆蓋你的信號處理程序。
設置信號(SIGINT和SIGTERM)處理,以便當用戶按下Ctrl-C時,將返回阻塞調用,如zmq_recv()和zmq_poll()。
它還說zctx
不贊成zsock
,根據其文檔似乎沒有設置信號處理程序。 所以我的第一個建議是使用新的zsock
套接字API。
但是,似乎在這兩種情況下你也可以調用zsys_handler_set(NULL);
( 此處記錄 )顯式禁用CZMQ中的默認SIGINT / SIGTERM處理。
PS: printf
不是異步信號安全的,這意味着它不應該用在信號處理程序中。 請參閱此處獲取POSIX中的異步信號安全功能列表。
在zmq mailing list
發布問題后得到了解決方案!
Pieter Hintjens說:: CZMQ
確實建立了自己的信號處理來捕獲SIGINT和SIGTERM。 你可以通過調用來禁用它
zsys_handler_set (NULL);
在我的代碼中添加上面的行禁用了czmq設置的信號處理程序,現在我可以使用自己的信號處理程序。
感謝Pieter Hintjens。
我認為您的問題與CZMQ無關,而且是由您的線程引起的。 具體來說,主線程正在捕獲信號,而子線程則沒有。 這是一個常見的陷阱。
有幾種解決方案。 我可能做的是在主線程中休眠/等待(例如,你可以使用zmq_poll)然后當你收到信號時,告訴孩子線程結束。
一些評論...如果你打算使用CZMQ,那么為什么不使用它的線程設置,它將pthreads包裝在一個更好的界面中。 你有舊的zthread類和更新的zactor類。
我認為你的主要計划應該還活着。 嘗試這個-
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
函數,該函數將為每個SIGINT
信號打印Interrupted
。
如果你需要你的程序希望在按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
函數中的信號表。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.