summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPanu Matilainen <pmatilai@redhat.com>2016-12-15 14:02:56 +0200
committerPanu Matilainen <pmatilai@redhat.com>2016-12-15 14:12:33 +0200
commit20f54a28cab83846e10251176d394d8d060adf29 (patch)
treee59c7cf57c28a86f04d9c5007a5cbab7e758e25b
parent4edaafc26fc4338ad25e993ef381aae3252dd7db (diff)
downloadrpm-20f54a28cab83846e10251176d394d8d060adf29.tar.gz
Add an shortcut API for blocking/unblocking signals
For rpm's purposes blocking all signals and restoring to previous status is the only necessary operation, make this part of the official API to make it available everywhere and replace rpmdb internal signal handling code with it. Noteworthy points: - The block/unblock operation is reference counted so these can be nested to arbitrary level without messing up things, much like the internal chroot API. - The rpmdb code used to remove rpmsq signals from the blocked mask, but blocked should really mean blocked, really. The pending signals will be delivered when unblocked and there's no need for us to mess with it. - Unlike the rpmdb variant, we now Run rpmsqPoll() *after* unblocking the signals. This actually matters now because rpmsqPoll() honors blocked signals since commit 07620f4ae7b626e6e02d743b1e933cf909ad0eb2.
-rw-r--r--lib/rpmdb.c14
-rw-r--r--rpmio/rpmsq.c27
-rw-r--r--rpmio/rpmsq.h9
3 files changed, 38 insertions, 12 deletions
diff --git a/lib/rpmdb.c b/lib/rpmdb.c
index e9ab15c5e..8104dcae5 100644
--- a/lib/rpmdb.c
+++ b/lib/rpmdb.c
@@ -332,16 +332,7 @@ void rpmAtExit(void)
*/
static int blockSignals(sigset_t * oldMask)
{
- sigset_t newMask;
-
- (void) sigfillset(&newMask); /* block all signals */
- (void) sigprocmask(SIG_BLOCK, &newMask, oldMask);
- (void) sigdelset(&newMask, SIGINT);
- (void) sigdelset(&newMask, SIGQUIT);
- (void) sigdelset(&newMask, SIGHUP);
- (void) sigdelset(&newMask, SIGTERM);
- (void) sigdelset(&newMask, SIGPIPE);
- return sigprocmask(SIG_BLOCK, &newMask, NULL);
+ return rpmsqBlock(SIG_BLOCK);
}
/**
@@ -349,8 +340,7 @@ static int blockSignals(sigset_t * oldMask)
*/
static int unblockSignals(sigset_t * oldMask)
{
- (void) rpmsqPoll();
- return sigprocmask(SIG_SETMASK, oldMask, NULL);
+ return rpmsqBlock(SIG_UNBLOCK);
}
rpmop rpmdbOp(rpmdb rpmdb, rpmdbOpX opx)
diff --git a/rpmio/rpmsq.c b/rpmio/rpmsq.c
index 1d0e73a6c..6dacd77bf 100644
--- a/rpmio/rpmsq.c
+++ b/rpmio/rpmsq.c
@@ -162,6 +162,33 @@ int rpmsqPoll(void)
return n;
}
+int rpmsqBlock(int op)
+{
+ static sigset_t oldMask;
+ static int blocked = 0;
+ sigset_t newMask;
+ int ret = 0;
+
+ if (op == SIG_BLOCK) {
+ blocked++;
+ if (blocked == 1) {
+ sigfillset(&newMask);
+ ret = sigprocmask(SIG_BLOCK, &newMask, &oldMask);
+ }
+ } else if (op == SIG_UNBLOCK) {
+ blocked--;
+ if (blocked == 0) {
+ ret = sigprocmask(SIG_SETMASK, &oldMask, NULL);
+ rpmsqPoll();
+ } else if (blocked < 0) {
+ blocked = 0;
+ ret = -1;
+ }
+ }
+
+ return ret;
+}
+
/** \ingroup rpmio
*
* By default, librpm will trap various unix signals such as SIGINT and SIGTERM,
diff --git a/rpmio/rpmsq.h b/rpmio/rpmsq.h
index 7a2cd8ba1..8cb2dc324 100644
--- a/rpmio/rpmsq.h
+++ b/rpmio/rpmsq.h
@@ -45,6 +45,15 @@ int rpmsqActivate(int state);
rpmsqAction_t rpmsqSetAction(int signum, rpmsqAction_t handler);
/** \ingroup rpmsq
+ * Block or unblock (all) signals.
+ * The operation is "reference counted" so the calls can be nested,
+ * and signals are only unblocked when the reference count falls to zero.
+ * @param op SIG_BLOCK/SIG_UNBLOCK
+ * @return 0 on success, -1 on error
+ */
+int rpmsqBlock(int op);
+
+/** \ingroup rpmsq
* Poll for caught signals, executing their handlers.
* @return no. active signals found
*/