diff options
author | Panu Matilainen <pmatilai@redhat.com> | 2016-12-15 14:02:56 +0200 |
---|---|---|
committer | Panu Matilainen <pmatilai@redhat.com> | 2016-12-15 14:12:33 +0200 |
commit | 20f54a28cab83846e10251176d394d8d060adf29 (patch) | |
tree | e59c7cf57c28a86f04d9c5007a5cbab7e758e25b | |
parent | 4edaafc26fc4338ad25e993ef381aae3252dd7db (diff) | |
download | rpm-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.c | 14 | ||||
-rw-r--r-- | rpmio/rpmsq.c | 27 | ||||
-rw-r--r-- | rpmio/rpmsq.h | 9 |
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 */ |