From cee579654f3dafea7ff9c0f9668558723889c0ab Mon Sep 17 00:00:00 2001 From: Azat Khuzhin Date: Sat, 1 Feb 2014 21:57:08 +0400 Subject: [PATCH] Add new evsignal_add_with_flags() for signal events By default libevent set SA_RESTART flag for sigaction(2), which will restart syscall automatically, and this is not always good. (That because it need to be compitable with signal(2), while it vary across systems) This patch add new function evsignal_add_with_flags(), which will change this flag from default SA_RESTART to user defined. --- event-internal.h | 3 ++- event.c | 10 ++++++++++ evmap.c | 2 +- include/event2/event.h | 7 +++++++ include/event2/event_struct.h | 2 ++ signal.c | 9 +++++---- 6 files changed, 27 insertions(+), 6 deletions(-) diff --git a/event-internal.h b/event-internal.h index 5208fbe087..04c103d11b 100644 --- a/event-internal.h +++ b/event-internal.h @@ -52,6 +52,7 @@ extern "C" { /* used only by signals */ #define ev_ncalls ev_.ev_signal.ev_ncalls #define ev_pncalls ev_.ev_signal.ev_pncalls +#define ev_sa_flags ev_.ev_signal.sa_flags #define ev_pri ev_evcallback.evcb_pri #define ev_flags ev_evcallback.evcb_flags @@ -400,7 +401,7 @@ struct event_config { ((base)->event_count_active) int evsig_set_handler_(struct event_base *base, int evsignal, - void (*fn)(int)); + void (*fn)(int), int); int evsig_restore_handler_(struct event_base *base, int evsignal); int event_add_nolock_(struct event *ev, diff --git a/event.c b/event.c index a5e8d0b1e9..247c47137b 100644 --- a/event.c +++ b/event.c @@ -2090,6 +2090,8 @@ event_new(struct event_base *base, evutil_socket_t fd, short events, void (*cb)( ev = mm_malloc(sizeof(struct event)); if (ev == NULL) return (NULL); + + ev->ev_sa_flags = SA_RESTART; if (event_assign(ev, base, fd, events, cb, arg) < 0) { mm_free(ev); return (NULL); @@ -2378,6 +2380,14 @@ event_add(struct event *ev, const struct timeval *tv) return (res); } +int +evsignal_add_with_flags(struct event *ev, const struct timeval *tv, int flags) +{ + ev->ev_sa_flags = flags; + + return evsignal_add(ev, tv); +} + /* Helper callback: wake an event_base from another thread. This version * works by writing a byte to one end of a socketpair, so that the event_base * listening on the other end will wake up as the corresponding event diff --git a/evmap.c b/evmap.c index 3f76dd0ae1..9c8f33cd2c 100644 --- a/evmap.c +++ b/evmap.c @@ -454,7 +454,7 @@ evmap_signal_add_(struct event_base *base, int sig, struct event *ev) base->evsigsel->fdinfo_len); if (LIST_EMPTY(&ctx->events)) { - if (evsel->add(base, ev->ev_fd, 0, EV_SIGNAL, NULL) + if (evsel->add(base, ev->ev_fd, 0, EV_SIGNAL, (void *)&ev->ev_sa_flags) == -1) return (-1); } diff --git a/include/event2/event.h b/include/event2/event.h index 6e2b884d44..3b684d8077 100644 --- a/include/event2/event.h +++ b/include/event2/event.h @@ -968,6 +968,13 @@ int event_base_got_break(struct event_base *); #define evtimer_initialized(ev) event_initialized(ev) /**@}*/ + +/** + * Change default sa_flags for sigaction(2) from SA_RESTART + * to user-specific. + */ +int evsignal_add_with_flags(struct event *, const struct timeval *, int); + /** @name evsignal_* macros diff --git a/include/event2/event_struct.h b/include/event2/event_struct.h index 1c8b71b6b0..19635712df 100644 --- a/include/event2/event_struct.h +++ b/include/event2/event_struct.h @@ -145,6 +145,8 @@ struct event { short ev_ncalls; /* Allows deletes in callback */ short *ev_pncalls; + /* Passed to sigaction(). */ + int sa_flags; } ev_signal; } ev_; diff --git a/signal.c b/signal.c index 3f46295024..c6c9b9e283 100644 --- a/signal.c +++ b/signal.c @@ -210,7 +210,8 @@ evsig_init_(struct event_base *base) * we can restore the original handler when we clear the current one. */ int evsig_set_handler_(struct event_base *base, - int evsignal, void (__cdecl *handler)(int)) + int evsignal, void (__cdecl *handler)(int), + int sa_flags) { #ifdef EVENT__HAVE_SIGACTION struct sigaction sa; @@ -252,7 +253,7 @@ evsig_set_handler_(struct event_base *base, #ifdef EVENT__HAVE_SIGACTION memset(&sa, 0, sizeof(sa)); sa.sa_handler = handler; - sa.sa_flags |= SA_RESTART; + sa.sa_flags |= sa_flags; sigfillset(&sa.sa_mask); if (sigaction(evsignal, &sa, sig->sh_old[evsignal]) == -1) { @@ -278,7 +279,7 @@ static int evsig_add(struct event_base *base, evutil_socket_t evsignal, short old, short events, void *p) { struct evsig_info *sig = &base->sig; - (void)p; + int sa_flags = *(int *)p; EVUTIL_ASSERT(evsignal >= 0 && evsignal < NSIG); @@ -299,7 +300,7 @@ evsig_add(struct event_base *base, evutil_socket_t evsignal, short old, short ev EVSIGBASE_UNLOCK(); event_debug(("%s: %d: changing signal handler", __func__, (int)evsignal)); - if (evsig_set_handler_(base, (int)evsignal, evsig_handler) == -1) { + if (evsig_set_handler_(base, (int)evsignal, evsig_handler, sa_flags) == -1) { goto err; }