Reputation: 791
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:
pthread_sigmask
to block signal in main thread which runs event loop.sigwait
to wait the signal in the watched thread, and notify the main thread by pipe.Thank you!
Upvotes: 1
Views: 2674
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