summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPanu Matilainen <pmatilai@redhat.com>2016-12-14 17:00:46 +0200
committerPanu Matilainen <pmatilai@redhat.com>2016-12-14 17:34:02 +0200
commit8c6c2a199dc1272b001913282aa2bee46ef58f26 (patch)
tree3c7c992dbc55a4bcbb91fbafe99aa5e4c757896b
parentf60131dae099fd58f7cacbdee112e22023c33867 (diff)
downloadrpm-8c6c2a199dc1272b001913282aa2bee46ef58f26.tar.gz
Make the signal queue actually customizable and useful
The original rpmsq API is somehow backwards and upside down: it allows overriding the handler when enabling the queue, but if the queue is to be enabled for a signal, then the only possible handler for it is the action that stores the signal in the queue. If you wanted to have some other kind of behavior you wouldn't want to enable the queue for that signal to begin with! What applications need is the ability to override what happens at signal poll, not arrival time - arrival time is at odds with the whole queue notion. So introduce a poll function which runs the handlers for caught signals, clearing them on the way. Add to that the notion of default handler which is called if no custom handler is set. Now this can be trivially used to replace the signal foobar inside rpmdb and suddenly applications can replace the standard behavior with a simple void my_sigint_handler(....) { /* do foo */ } rpmsqEnable(SIGINT, my_sigint_handler); ...and the custom hander will be called when a SIGINT has arrived and the next signal polling round from rpmdb internals or whever occurs. rpmsqAction() is removed from the API/ABI here, but it's not as if it ever was useful to anybody anyway.
-rw-r--r--lib/rpmdb.c27
-rw-r--r--rpmio/rpmsq.c50
-rw-r--r--rpmio/rpmsq.h16
3 files changed, 47 insertions, 46 deletions
diff --git a/lib/rpmdb.c b/lib/rpmdb.c
index 545e0517c..ca166335f 100644
--- a/lib/rpmdb.c
+++ b/lib/rpmdb.c
@@ -327,34 +327,9 @@ void rpmAtExit(void)
(void) rpmdbClose(db);
}
-static int rpmdbCheckTerminate(void)
-{
- sigset_t newMask, oldMask;
- int terminating = 0;
-
- (void) sigfillset(&newMask); /* block all signals */
- (void) sigprocmask(SIG_BLOCK, &newMask, &oldMask);
-
- if (rpmsqIsCaught(SIGINT) > 0
- || rpmsqIsCaught(SIGQUIT) > 0
- || rpmsqIsCaught(SIGHUP) > 0
- || rpmsqIsCaught(SIGTERM) > 0
- || rpmsqIsCaught(SIGPIPE) > 0)
- terminating = 1;
-
- sigprocmask(SIG_SETMASK, &oldMask, NULL);
- return terminating;
-}
-
int rpmdbCheckSignals(void)
{
- static int terminating = 0;
- if (!terminating && rpmdbCheckTerminate()) {
- terminating = 1;
- rpmlog(RPMLOG_DEBUG, "Exiting on signal...\n");
- exit(EXIT_FAILURE);
- }
- return 0;
+ return rpmsqPoll();
}
/**
diff --git a/rpmio/rpmsq.c b/rpmio/rpmsq.c
index 9d0713b1e..7a725b99c 100644
--- a/rpmio/rpmsq.c
+++ b/rpmio/rpmsq.c
@@ -11,6 +11,7 @@
#include <stdlib.h>
#include <rpm/rpmsq.h>
+#include <rpm/rpmlog.h>
#include "debug.h"
@@ -20,17 +21,24 @@ static sigset_t rpmsqActive;
typedef struct rpmsig_s * rpmsig;
+static void rpmsqTerm(int signum, siginfo_t *info, void *context)
+{
+ rpmlog(RPMLOG_DEBUG, "exiting on signal...\n");
+ exit(EXIT_FAILURE);
+}
+
static struct rpmsig_s {
int signum;
+ rpmsqAction_t defhandler;
rpmsqAction_t handler;
struct sigaction oact;
} rpmsigTbl[] = {
- { SIGINT, rpmsqAction },
- { SIGQUIT, rpmsqAction },
- { SIGHUP, rpmsqAction },
- { SIGTERM, rpmsqAction },
- { SIGPIPE, rpmsqAction },
- { -1, NULL },
+ { SIGINT, rpmsqTerm, NULL },
+ { SIGQUIT, rpmsqTerm, NULL },
+ { SIGHUP, rpmsqTerm, NULL },
+ { SIGTERM, rpmsqTerm, NULL },
+ { SIGPIPE, rpmsqTerm, NULL },
+ { -1, NULL, NULL },
};
int rpmsqIsCaught(int signum)
@@ -38,7 +46,7 @@ int rpmsqIsCaught(int signum)
return sigismember(&rpmsqCaught, signum);
}
-void rpmsqAction(int signum, siginfo_t * info, void * context)
+static void rpmsqAction(int signum, siginfo_t * info, void * context)
{
int save = errno;
@@ -73,19 +81,18 @@ int rpmsqEnable(int signum, rpmsqAction_t handler)
(void) sigemptyset (&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
- sa.sa_sigaction = (handler != NULL ? handler : tbl->handler);
+ sa.sa_sigaction = rpmsqAction;
if (sigaction(tbl->signum, &sa, &tbl->oact) < 0)
break;
sigaddset(&rpmsqActive, tblsignum);
- if (handler != NULL)
- tbl->handler = handler;
+ tbl->handler = (handler != NULL) ? handler : tbl->defhandler;
}
} else { /* Disable. */
if (sigismember(&rpmsqActive, tblsignum)) {
if (sigaction(tbl->signum, &tbl->oact, NULL) < 0)
break;
sigdelset(&rpmsqActive, tblsignum);
- tbl->handler = (handler != NULL ? handler : rpmsqAction);
+ tbl->handler = NULL;
}
}
ret = sigismember(&rpmsqActive, tblsignum);
@@ -94,6 +101,27 @@ int rpmsqEnable(int signum, rpmsqAction_t handler)
return ret;
}
+int rpmsqPoll(void)
+{
+ sigset_t newMask, oldMask;
+ int n = 0;
+
+ /* block all signals while processing the queue */
+ (void) sigfillset(&newMask);
+ (void) sigprocmask(SIG_BLOCK, &newMask, &oldMask);
+
+ for (rpmsig tbl = rpmsigTbl; tbl->signum >= 0; tbl++) {
+ if (sigismember(&rpmsqCaught, tbl->signum)) {
+ n++;
+ /* delete signal before running handler to prevent recursing */
+ sigdelset(&rpmsqCaught, tbl->signum);
+ if (tbl->handler)
+ tbl->handler(tbl->signum, NULL, NULL);
+ }
+ }
+ sigprocmask(SIG_SETMASK, &oldMask, NULL);
+ return n;
+}
/** \ingroup rpmio
*
diff --git a/rpmio/rpmsq.h b/rpmio/rpmsq.h
index f174f159c..f22c8f525 100644
--- a/rpmio/rpmsq.h
+++ b/rpmio/rpmsq.h
@@ -30,21 +30,19 @@ typedef void (*rpmsqAction_t) (int signum, siginfo_t * info, void * context);
int rpmsqIsCaught(int signum);
/** \ingroup rpmsq
- * Default signal handler.
- * @param signum signal number
- * @param info (siginfo_t) signal info
- * @param context signal context
- */
-void rpmsqAction(int signum, siginfo_t * info, void * context);
-
-/** \ingroup rpmsq
* Enable or disable a signal handler.
* @param signum signal to enable (or disable if negative)
- * @param handler sa_sigaction handler (or NULL to use rpmsqHandler())
+ * @param handler signal handler (or NULL to use default)
* @return no. of refs, -1 on error
*/
int rpmsqEnable(int signum, rpmsqAction_t handler);
+/** \ingroup rpmsq
+ * Poll for caught signals, executing their handlers.
+ * @return no. active signals found
+ */
+int rpmsqPoll(void);
+
void rpmsqSetInterruptSafety(int on);
#ifdef __cplusplus