信号处理程序不工作

时间:2014-08-14 09:26:26

标签: c pthreads zeromq

我在代码中使用czmqzmq个库。我通过调用main中的SIGINTsignal注册了一个信号处理程序。代码如下所示:

#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库有什么问题?应该如何处理?

5 个答案:

答案 0 :(得分:6)

documentation for zctx表示zctxSIGINTSIGTERM设置了自己的信号处理程序,可能会覆盖您的信号处理程序。

  

设置信号(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)

  

问题是什么......

来自man signal

  

未指定signal()在多线程进程中的效果。

改为使用sigaction()

答案 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函数中的信号表。