sfzhang
sfzhang

Reputation: 791

How to use signal event of libevent in correct way

libevent supports to notify when watched signals arrived. It seems that the signals could interrupt at anywhere of the code on Linux/Unix (Is it right?) . Does it mean that, I should check the return value and errno is equal EINTR after invoked all system calls and other library functions? There is the simple test code.

#include <stdio.h>
#include <signal.h>
int i = 0;
void handle(int signo)
{
    printf("i[%d], signo[%d]\n", i, signo);
}

int main()
{
    signal(SIGINT, handle);
    while (1) {
        i++;
    }   
    return 0;
}

After run this code, and press several Ctrl+C, get the following output:

 ./signal 
^Ci[475151517], signo[2]
^Ci[656118185], signo[2]
^Ci[891673397], signo[2]
^Ci[1668347228], signo[2]
^Ci[-2123628990], signo[2]

It seems that sigint interrupts at i++. If the above conjecture is right, is it the right way to handle the signal like this:

Thank you!

Upvotes: 1

Views: 2674

Answers (1)

Moises Silva
Moises Silva

Reputation: 161

Yes, a signal may interrupt execution anywhere (unless masked) and yes it means all system calls (I'm not sure if there are some exceptions though?) such as write/read/poll will return a EINT when interrupted by a signal (you may want to read the man page for pselect, particularly the 'BUGS' section). This is known as the 'PC loser-ing problem'

You should use libevent native support for signal handling. Check out all the macros 'evsignal_xxx' in their documentation.

In a nutshell, you do something like this:

struct event ev_sigint;
struct event_base *ev_base;
ev_base = event_init();
evsignal_set(&ev_sigint, SIGINT, sighandler, ev_base);
evsignal_add(&ev_sigint, NULL);
event_dispatch();

Then from your signal handler you break the loop:

void sighandler(int signal, short events, void *base)
{
    event_base_loopbreak(base);
}

Upvotes: 0

Related Questions