X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;ds=sidebyside;f=rpmio%2Frpmsq.c;h=bfd4db004c34c07e889c48a927e68289ccbc8d93;hb=6b52f62e25ed30e68b4997fac0c52ad1876d4665;hp=52180b64c6593f81b4d94c329acda192e2587664;hpb=77b724ec9940a01f435cc20a2a5f0445a14ef276;p=platform%2Fupstream%2Frpm.git diff --git a/rpmio/rpmsq.c b/rpmio/rpmsq.c index 52180b6..bfd4db0 100644 --- a/rpmio/rpmsq.c +++ b/rpmio/rpmsq.c @@ -3,88 +3,54 @@ */ #include "system.h" - -#if defined(HAVE_PTHREAD_H) && !defined(__LCLINT__) -#include -#endif - -#include -#include "debug.h" +#include +#include +#include +#include -/*@unchecked@*/ -static struct rpmsqElem rpmsqRock; -/*@unchecked@*/ -rpmsq rpmsqQueue = &rpmsqRock; +#define ADD_REF(__tbl) (__tbl)->active++ +#define SUB_REF(__tbl) --(__tbl)->active -void Insque(void * elem, void * prev) -{ - if (elem != NULL) - insque(elem, (prev ? prev : rpmsqQueue)); -} +#include -void Remque(void * elem) -{ - if (elem != NULL) - remque(elem); -} +#include "debug.h" -/*@unchecked@*/ -sigset_t rpmsqCaught; +static sigset_t rpmsqCaught; -/*@unchecked@*/ -static pthread_mutex_t rpmsigTbl_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; +typedef struct rpmsig_s * rpmsig; -/*@unchecked@*/ -/*@-fullinitblock@*/ static struct rpmsig_s { int signum; - void (*handler) (int signum); + rpmsqAction_t handler; int active; struct sigaction oact; } rpmsigTbl[] = { - { SIGINT, rpmsqHandler }, + { SIGINT, rpmsqAction }, #define rpmsigTbl_sigint (&rpmsigTbl[0]) - { SIGQUIT, rpmsqHandler }, + { SIGQUIT, rpmsqAction }, #define rpmsigTbl_sigquit (&rpmsigTbl[1]) - { SIGCHLD, rpmsqHandler }, -#define rpmsigTbl_sigchld (&rpmsigTbl[2]) - -#define DO_LOCK() pthread_mutex_lock(&rpmsigTbl_lock); -#define DO_UNLOCK() pthread_mutex_unlock(&rpmsigTbl_lock); -#define INIT_LOCK() \ - { pthread_mutexattr_t attr; \ - pthread_mutexattr_init(&attr); \ - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); \ - pthread_mutex_init (&rpmsigTbl_lock, &attr); \ - pthread_mutexattr_destroy(&attr); \ - rpmsigTbl_sigchld->active = 0; \ - } -#define ADD_REF(__tbl) (__tbl)->active++ -#define SUB_REF(__tbl) --(__tbl)->active - -#define CLEANUP_HANDLER(__handler, __arg, __oldtypeptr) \ - pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, (__oldtypeptr)); \ - pthread_cleanup_push((__handler), (__arg)); -#define CLEANUP_RESET(__execute, __oldtype) \ - pthread_cleanup_pop(__execute); \ - pthread_setcanceltype ((__oldtype), &(__oldtype)); - - { SIGHUP, rpmsqHandler }, + { SIGHUP, rpmsqAction }, #define rpmsigTbl_sighup (&rpmsigTbl[3]) - { SIGTERM, rpmsqHandler }, + { SIGTERM, rpmsqAction }, #define rpmsigTbl_sigterm (&rpmsigTbl[4]) - { SIGPIPE, rpmsqHandler }, + { SIGPIPE, rpmsqAction }, #define rpmsigTbl_sigpipe (&rpmsigTbl[5]) { -1, NULL }, }; -/*@=fullinitblock@*/ -/** - */ -/*@-incondefs@*/ -void rpmsqHandler(int signum) +int rpmsqIsCaught(int signum) { + return sigismember(&rpmsqCaught, signum); +} + +#ifdef SA_SIGINFO +void rpmsqAction(int signum, siginfo_t * info, void * context) +#else +void rpmsqAction(int signum) +#endif +{ + int save = errno; rpmsig tbl; for (tbl = rpmsigTbl; tbl->signum >= 0; tbl++) { @@ -92,181 +58,57 @@ void rpmsqHandler(int signum) continue; (void) sigaddset(&rpmsqCaught, signum); - - switch (signum) { - case SIGCHLD: - while (1) { - rpmsq sq; - int status = 0; - pid_t reaped = waitpid(0, &status, WNOHANG); - - if (reaped <= 0) - /*@innerbreak@*/ break; - - for (sq = rpmsqQueue->q_forw; - sq != NULL && sq != rpmsqQueue; - sq = sq->q_forw) - { - if (sq->child != reaped) - /*@innercontinue@*/ continue; - sq->reaped = reaped; - sq->status = status; - /*@innerbreak@*/ break; - } - } - /*@switchbreak@*/ break; - default: - /*@switchbreak@*/ break; - } break; } + errno = save; } -/*@=incondefs@*/ -/** - * Enable or disable a signal handler. - * @param signum signal to enable (or disable if negative) - * @param handler signal handler (or NULL to use rpmsqHandler()) - * @return no. of refs, -1 on error - */ -int rpmsqEnable(int signum, /*@null@*/ sighandler_t handler) - /*@globals rpmsqCaught, rpmsigTbl @*/ - /*@modifies rpmsqCaught, rpmsigTbl @*/ +int rpmsqEnable(int signum, rpmsqAction_t handler) { int tblsignum = (signum >= 0 ? signum : -signum); struct sigaction sa; rpmsig tbl; int ret = -1; - DO_LOCK (); for (tbl = rpmsigTbl; tbl->signum >= 0; tbl++) { if (tblsignum != tbl->signum) continue; if (signum >= 0) { /* Enable. */ if (ADD_REF(tbl) <= 0) { - tbl->active = 1; /* XXX just in case */ (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); +#ifdef SA_SIGINFO + sa.sa_flags = SA_SIGINFO; +#else sa.sa_flags = 0; - sigemptyset (&sa.sa_mask); - sa.sa_handler = (handler != NULL ? handler : tbl->handler); +#endif + sa.sa_sigaction = (handler != NULL ? handler : tbl->handler); if (sigaction(tbl->signum, &sa, &tbl->oact) < 0) { SUB_REF(tbl); break; } + tbl->active = 1; /* XXX just in case */ + if (handler != NULL) + tbl->handler = handler; } } else { /* Disable. */ if (SUB_REF(tbl) <= 0) { - tbl->active = 0; /* XXX just in case */ if (sigaction(tbl->signum, &tbl->oact, NULL) < 0) break; + tbl->active = 0; /* XXX just in case */ + tbl->handler = (handler != NULL ? handler : rpmsqAction); } } ret = tbl->active; break; } - DO_UNLOCK (); return ret; } -/** - * SIGCHLD cancellation handler. - */ -static void -sigchld_cancel (void *arg) -{ - pid_t child = *(pid_t *) arg; - pid_t result; - - (void) kill(child, SIGKILL); - - do { - result = waitpid(child, NULL, 0); - } while (result == (pid_t)-1 && errno == EINTR); - - DO_LOCK (); - if (SUB_REF (rpmsigTbl_sigchld) == 0) { - (void) rpmsqEnable(-SIGQUIT, NULL); - (void) rpmsqEnable(-SIGINT, NULL); - } - DO_UNLOCK (); -} - -/** - * Execute a command, returning its status. - */ -int -rpmsqExecve (const char ** argv) -{ - int oldtype; - int status = -1; - pid_t pid; - pid_t result; - sigset_t newMask, oldMask; - - DO_LOCK (); - if (ADD_REF (rpmsigTbl_sigchld) == 0) { - if (rpmsqEnable(SIGINT, NULL) < 0) { - SUB_REF (rpmsigTbl_sigchld); - goto out; - } - if (rpmsqEnable(SIGQUIT, NULL) < 0) { - SUB_REF (rpmsigTbl_sigchld); - goto out_restore_sigint; - } - } - DO_UNLOCK (); - - sigemptyset (&newMask); - sigaddset (&newMask, SIGCHLD); - if (sigprocmask (SIG_BLOCK, &newMask, &oldMask) < 0) { - DO_LOCK (); - if (SUB_REF (rpmsigTbl_sigchld) == 0) - goto out_restore_sigquit_and_sigint; - goto out; - } - - CLEANUP_HANDLER(sigchld_cancel, &pid, &oldtype); - - pid = fork (); - if (pid < (pid_t) 0) { /* fork failed. */ - goto out; - } else if (pid == (pid_t) 0) { /* Child. */ - - /* Restore the signals. */ - (void) sigaction (SIGINT, &rpmsigTbl_sigint->oact, NULL); - (void) sigaction (SIGQUIT, &rpmsigTbl_sigquit->oact, NULL); - (void) sigprocmask (SIG_SETMASK, &oldMask, NULL); - - /* Reset rpmsigTbl lock and refcnt. */ - INIT_LOCK (); - - (void) execve (argv[0], (char *const *) argv, environ); - _exit (127); - } else { /* Parent. */ - do { - result = waitpid(pid, &status, 0); - } while (result == (pid_t)-1 && errno == EINTR); - if (result != pid) - status = -1; - } - - CLEANUP_RESET(0, oldtype); - - DO_LOCK (); - if ((SUB_REF (rpmsigTbl_sigchld) == 0 && - (rpmsqEnable(-SIGINT, NULL) < 0 || rpmsqEnable (-SIGQUIT, NULL) < 0)) - || sigprocmask (SIG_SETMASK, &oldMask, (sigset_t *) NULL) != 0) - { - status = -1; - } - goto out; - -out_restore_sigquit_and_sigint: - (void) rpmsqEnable(-SIGQUIT, NULL); -out_restore_sigint: - (void) rpmsqEnable(-SIGINT, NULL); -out: - DO_UNLOCK (); - return status; -}