簡體   English   中英

信號處理程序不工作

[英]signal handler not working

我在我的代碼中使用czmqzmq庫。 我已經注冊了一個信號處理程序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中斷時,上面的代碼沒有進入信號處理程序。

czmqzmq庫有什么問題以及應該如何處理?

zctx文檔zctxSIGINTSIGTERM設置了自己的信號處理程序,可能會覆蓋你的信號處理程序。

設置信號(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。

問題是什么 ...

來自man signal

signal()在多線程進程中的影響未指定。

請改用sigaction()

我認為您的問題與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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM