diff options
-rw-r--r-- | lib/rpmdb.c | 12 | ||||
-rw-r--r-- | rpmio/rpmsq.c | 89 | ||||
-rw-r--r-- | rpmio/rpmsq.h | 17 |
3 files changed, 63 insertions, 55 deletions
diff --git a/lib/rpmdb.c b/lib/rpmdb.c index 82b083e00..e9ab15c5e 100644 --- a/lib/rpmdb.c +++ b/lib/rpmdb.c @@ -451,11 +451,7 @@ int rpmdbClose(rpmdb db) db = _free(db); if (rpmdbRock == NULL) { - (void) rpmsqEnable(-SIGHUP, NULL); - (void) rpmsqEnable(-SIGINT, NULL); - (void) rpmsqEnable(-SIGTERM, NULL); - (void) rpmsqEnable(-SIGQUIT, NULL); - (void) rpmsqEnable(-SIGPIPE, NULL); + rpmsqActivate(0); } exit: return rc; @@ -536,11 +532,7 @@ static int openDatabase(const char * prefix, rc = rpmioMkpath(rpmdbHome(db), 0755, getuid(), getgid()); if (rc == 0) { if (rpmdbRock == NULL) { - (void) rpmsqEnable(SIGHUP, NULL); - (void) rpmsqEnable(SIGINT, NULL); - (void) rpmsqEnable(SIGTERM, NULL); - (void) rpmsqEnable(SIGQUIT, NULL); - (void) rpmsqEnable(SIGPIPE, NULL); + rpmsqActivate(1); } /* Just the primary Packages database opened here */ diff --git a/rpmio/rpmsq.c b/rpmio/rpmsq.c index 74dc24ce7..c2efb4714 100644 --- a/rpmio/rpmsq.c +++ b/rpmio/rpmsq.c @@ -79,49 +79,58 @@ static void rpmsqHandler(int signum, siginfo_t * info, void * context) errno = save; } -int rpmsqEnable(int signum, rpmsqAction_t handler) +rpmsqAction_t rpmsqSetAction(int signum, rpmsqAction_t handler) { - int tblsignum = abs(signum); - struct sigaction sa; - rpmsig tbl; - int ret = -1; + rpmsig sig = NULL; + rpmsqAction_t oh = NULL; + + if (rpmsigGet(signum, &sig)) { + oh = sig->handler; + sig->handler = handler; + } + return oh; +} + +int rpmsqActivate(int state) +{ + sigset_t newMask, oldMask; if (disableInterruptSafety) return 0; - for (tbl = rpmsigTbl; tbl->signum >= 0; tbl++) { - if (tblsignum != tbl->signum) - continue; - - if (signum >= 0) { /* Enable. */ - if (!sigismember(&rpmsqActive, tblsignum)) { - (void) sigdelset(&rpmsqCaught, tbl->signum); - - /* XXX Don't set a signal handler if already SIG_IGN */ - (void) sigaction(tbl->signum, NULL, &tbl->oact); - if (tbl->oact.sa_handler == SIG_IGN) - continue; - - (void) sigemptyset (&sa.sa_mask); - sa.sa_flags = SA_SIGINFO; - sa.sa_sigaction = rpmsqHandler; - if (sigaction(tbl->signum, &sa, &tbl->oact) < 0) - break; - sigaddset(&rpmsqActive, tblsignum); - 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 = NULL; + (void) sigfillset(&newMask); + (void) sigprocmask(SIG_BLOCK, &newMask, &oldMask); + + if (state) { + struct sigaction sa; + for (rpmsig tbl = rpmsigTbl; tbl->signum >= 0; tbl++) { + sigdelset(&rpmsqCaught, tbl->signum); + memset(&tbl->siginfo, 0, sizeof(tbl->siginfo)); + + /* XXX Don't set a signal handler if already SIG_IGN */ + sigaction(tbl->signum, NULL, &tbl->oact); + if (tbl->oact.sa_handler == SIG_IGN) + continue; + + sigemptyset (&sa.sa_mask); + sa.sa_flags = SA_SIGINFO; + sa.sa_sigaction = rpmsqHandler; + if (sigaction(tbl->signum, &sa, &tbl->oact) == 0) + sigaddset(&rpmsqActive, tbl->signum); + } + } else { + for (rpmsig tbl = rpmsigTbl; tbl->signum >= 0; tbl++) { + if (!sigismember(&rpmsqActive, tbl->signum)) + continue; + if (sigaction(tbl->signum, &tbl->oact, NULL) == 0) { + sigdelset(&rpmsqActive, tbl->signum); + sigdelset(&rpmsqCaught, tbl->signum); + memset(&tbl->siginfo, 0, sizeof(tbl->siginfo)); } } - ret = sigismember(&rpmsqActive, tblsignum); - break; } - return ret; + sigprocmask(SIG_SETMASK, &oldMask, NULL); + return 0; } int rpmsqPoll(void) @@ -135,13 +144,13 @@ int rpmsqPoll(void) for (rpmsig tbl = rpmsigTbl; tbl->signum >= 0; tbl++) { if (sigismember(&rpmsqCaught, tbl->signum)) { - n++; + rpmsqAction_t handler = (tbl->handler != NULL) ? tbl->handler : + tbl->defhandler; /* delete signal before running handler to prevent recursing */ sigdelset(&rpmsqCaught, tbl->signum); - if (tbl->handler) { - tbl->handler(tbl->signum, &tbl->siginfo, NULL); - memset(&tbl->siginfo, 0, sizeof(tbl->siginfo)); - } + handler(tbl->signum, &tbl->siginfo, NULL); + memset(&tbl->siginfo, 0, sizeof(tbl->siginfo)); + n++; } } sigprocmask(SIG_SETMASK, &oldMask, NULL); diff --git a/rpmio/rpmsq.h b/rpmio/rpmsq.h index f22c8f525..7a2cd8ba1 100644 --- a/rpmio/rpmsq.h +++ b/rpmio/rpmsq.h @@ -30,12 +30,19 @@ typedef void (*rpmsqAction_t) (int signum, siginfo_t * info, void * context); int rpmsqIsCaught(int signum); /** \ingroup rpmsq - * Enable or disable a signal handler. - * @param signum signal to enable (or disable if negative) - * @param handler signal handler (or NULL to use default) - * @return no. of refs, -1 on error + * Activate (or disable) the signal queue. + * @param state 1 to enable, 0 to disable + * @return 0 on success, negative on error */ -int rpmsqEnable(int signum, rpmsqAction_t handler); +int rpmsqActivate(int state); + +/** \ingroup rpmsq + * Set or delete a signal handler for a signal. + * @param signum signal number + * @param handler signal handler or NULL to delete + * @return previous non-default handler (possibly NULL) + */ +rpmsqAction_t rpmsqSetAction(int signum, rpmsqAction_t handler); /** \ingroup rpmsq * Poll for caught signals, executing their handlers. |