tthread: tthread.o librpm.la
$(LINK) $(CFLAGS) $(DEFS) $(INCLUDES) -o $@ $< $(mylibs) @WITH_LIBELF_LIB@
-tsystem: tsystem.o
- $(LINK) $(CFLAGS) $(DEFS) $(INCLUDES) -o $@ $< -lpthread
+tsystem: tsystem.o $(top_builddir)/popt/libpopt.la
+ $(LINK) $(CFLAGS) $(DEFS) $(INCLUDES) -o $@ $< $(top_builddir)/rpmio/librpmio.la $(top_builddir)/popt/libpopt.la
tplatform: tplatform.o librpm.la
$(LINK) @LDFLAGS_STATIC@ $(CFLAGS) $(DEFS) $(INCLUDES) -o $@ $< $(mylibs)
#include "system.h"
-#include <signal.h>
-#include <sys/signal.h>
-
#include <rpmio_internal.h>
#include <rpmlib.h>
#include <rpmmacro.h>
#include <rpmurl.h>
+#include <rpmsq.h>
#include "cpio.h"
#include "fsm.h" /* XXX CPIO_FOO/FSM_FOO constants */
}
/**
- */
-/*@unchecked@*/
-static sigset_t caught;
-
-/**
- */
-/*@unchecked@*/
-static struct psmtbl_s {
- int nalloced;
- int npsms;
-/*@null@*/
- rpmpsm * psms;
-} psmtbl = { 0, 0, NULL };
-
-/* forward ref */
-static void handler(int signum)
- /*@globals caught, psmtbl, fileSystem @*/
- /*@modifies caught, psmtbl, fileSystem @*/;
-
-/**
- */
-/*@unchecked@*/
-/*@-fullinitblock@*/
-static struct sigtbl_s {
- int signum;
- int active;
- void (*handler) (int signum);
- struct sigaction oact;
-} satbl[] = {
- { SIGCHLD, 0, handler },
- { -1, 0, NULL },
-};
-/*@=fullinitblock@*/
-
-/**
- */
-/*@-incondefs@*/
-static void handler(int signum)
-{
- struct sigtbl_s * tbl;
-
- for(tbl = satbl; tbl->signum >= 0; tbl++) {
- if (tbl->signum != signum)
- continue;
- if (!tbl->active)
- continue;
- (void) sigaddset(&caught, signum);
- switch (signum) {
- case SIGCHLD:
- while (1) {
- int status = 0;
- pid_t reaped = waitpid(0, &status, WNOHANG);
- int i;
-
- if (reaped <= 0)
- /*@innerbreak@*/ break;
-
- if (psmtbl.psms)
- for (i = 0; i < psmtbl.npsms; i++) {
- rpmpsm psm = psmtbl.psms[i];
- if (psm->child != reaped)
- /*@innercontinue@*/ continue;
-
-#if _PSM_DEBUG
-/*@-modfilesys@*/
-if (_psm_debug)
-fprintf(stderr, " Reap: %p[%d:%d:%d] = %p child %d\n", psmtbl.psms, i, psmtbl.npsms, psmtbl.nalloced, psm, psm->child);
-/*@=modfilesys@*/
-#endif
-
- psm->reaped = reaped;
- psm->status = status;
- /*@innerbreak@*/ break;
- }
- }
- /*@switchbreak@*/ break;
- default:
- /*@switchbreak@*/ break;
- }
- break;
- }
-}
-/*@=incondefs@*/
-
-/**
- * Enable a signal handler.
- */
-static int enableSignal(int signum)
- /*@globals caught, satbl, fileSystem @*/
- /*@modifies caught, satbl, fileSystem @*/
-{
- sigset_t newMask, oldMask;
- struct sigtbl_s * tbl;
- struct sigaction act;
-
- (void) sigfillset(&newMask); /* block all signals */
- (void) sigprocmask(SIG_BLOCK, &newMask, &oldMask);
- for (tbl = satbl; tbl->signum >= 0; tbl++) {
- if (signum >= 0 && signum != tbl->signum)
- continue;
-/*@-modfilesys@*/
-if (_psm_debug)
-fprintf(stderr, " Enable: %p[0:%d:%d] active %d\n", psmtbl.psms, psmtbl.npsms, psmtbl.nalloced, tbl->active);
-/*@=modfilesys@*/
- if (tbl->active++ <= 0) {
- (void) sigdelset(&caught, tbl->signum);
- memset(&act, 0, sizeof(act));
- act.sa_handler = tbl->handler;
- (void) sigaction(tbl->signum, &act, &tbl->oact);
- }
- break;
- }
- return sigprocmask(SIG_SETMASK, &oldMask, NULL);
-}
-
-/**
- * Disable a signal handler.
- */
-static int disableSignal(int signum)
- /*@globals satbl, fileSystem @*/
- /*@modifies satbl, fileSystem @*/
-{
- sigset_t newMask, oldMask;
- struct sigtbl_s * tbl;
-
- (void) sigfillset(&newMask); /* block all signals */
- (void) sigprocmask(SIG_BLOCK, &newMask, &oldMask);
- for (tbl = satbl; tbl->signum >= 0; tbl++) {
- if (signum >= 0 && signum != tbl->signum)
- continue;
-/*@-modfilesys@*/
-if (_psm_debug)
-fprintf(stderr, " Disable: %p[0:%d:%d] active %d\n", psmtbl.psms, psmtbl.npsms, psmtbl.nalloced, tbl->active);
-/*@=modfilesys@*/
- if (--tbl->active <= 0) {
- tbl->active = 0; /* XXX just in case */
- (void) sigaction(tbl->signum, &tbl->oact, NULL);
- }
- break;
- }
- return sigprocmask(SIG_SETMASK, &oldMask, NULL);
-}
-
-/**
* Register a child reaper, then fork a child.
* @param psm package state machine data
* @return fork(2) pid
*/
static pid_t psmRegisterFork(rpmpsm psm)
- /*@globals psmtbl, fileSystem, internalState @*/
- /*@modifies psm, psmtbl, fileSystem, internalState @*/
+ /*@globals fileSystem, internalState @*/
+ /*@modifies psm, fileSystem, internalState @*/
{
sigset_t newMask, oldMask;
- int empty = -1;
- int i = psmtbl.npsms;
(void) sigfillset(&newMask); /* block all signals */
(void) sigprocmask(SIG_BLOCK, &newMask, &oldMask);
if (psm->reaper) {
- if (psmtbl.psms)
- for (i = 0; i < psmtbl.npsms; i++) {
- if (empty == -1 && psmtbl.psms[i] == NULL)
- empty = i;
- if (psm != psmtbl.psms[i])
- continue;
- break;
- }
- if (i == psmtbl.npsms) {
- if (i >= psmtbl.nalloced) {
- if (psmtbl.nalloced == 0) psmtbl.nalloced = 5;
- while (psmtbl.nalloced < i)
- psmtbl.nalloced += psmtbl.nalloced;
- psmtbl.psms = xrealloc(psmtbl.psms,
- psmtbl.nalloced * sizeof(*psmtbl.psms));
- }
- empty = psmtbl.npsms++;
- }
- if (psmtbl.psms) /* XXX can't happen */
- psmtbl.psms[empty] = rpmpsmLink(psm, "psmRegister");
+ Insque(psm, NULL);
/*@-modfilesys@*/
if (_psm_debug)
-fprintf(stderr, " Register: %p[%d:%d:%d] = %p\n", psmtbl.psms, empty, psmtbl.npsms, psmtbl.nalloced, psm);
+fprintf(stderr, " Register: %p\n", psm);
/*@=modfilesys@*/
- (void) enableSignal(SIGCHLD);
+ (void) rpmsqEnable(SIGCHLD, NULL);
}
psm->reaped = 0;
if ((psm->child = fork()) != 0) {
/*@-modfilesys@*/
if (_psm_debug)
-fprintf(stderr, " Fork: %p[%d:%d:%d] = %p child %d\n", psmtbl.psms, 0, psmtbl.npsms, psmtbl.nalloced, psm, psm->child);
+fprintf(stderr, " Fork: %p child %d\n", psm, psm->child);
/*@=modfilesys@*/
}
* Unregister a child reaper.
*/
static int psmWaitUnregister(rpmpsm psm, pid_t child)
- /*@globals psmtbl, fileSystem, internalState @*/
- /*@modifies psmtbl, fileSystem, internalState @*/
+ /*@globals fileSystem, internalState @*/
+ /*@modifies fileSystem, internalState @*/
{
sigset_t newMask, oldMask;
- int i = 0;
(void) sigfillset(&newMask); /* block all signals */
(void) sigprocmask(SIG_BLOCK, &newMask, &oldMask);
/*@-modfilesys@*/
if (_psm_debug)
-fprintf(stderr, " Wait: %p[%d:%d:%d] = %p child %d\n", psmtbl.psms, 0, psmtbl.npsms, psmtbl.nalloced, psm, psm->child);
+fprintf(stderr, " Wait: %p child %d\n", psm, psm->child);
/*@=modfilesys@*/
- if (psmtbl.psms)
- for (i = 0; i < psmtbl.npsms; i++) {
- if (psmtbl.psms[i] == NULL)
- continue;
- if (psm != psmtbl.psms[i])
- continue;
- if (child != psm->child)
- continue;
- break;
- }
-
- if (i < psmtbl.npsms) {
- (void) disableSignal(SIGCHLD);
+ if (psm->reaper) {
+ Remque(psm);
+ (void) rpmsqEnable(-SIGCHLD, NULL);
/*@-modfilesys@*/
if (_psm_debug)
-fprintf(stderr, "Unregister: %p[%d:%d:%d] = %p child %d\n", psmtbl.psms, i, psmtbl.npsms, psmtbl.nalloced, psm, child);
+fprintf(stderr, "Unregister: %p child %d\n", psm, child);
/*@=modfilesys@*/
- if (psmtbl.psms) /* XXX can't happen */
- psmtbl.psms[i] = rpmpsmFree(psmtbl.psms[i]);
- if (psmtbl.npsms == (i+1))
- psmtbl.npsms--;
- if (psmtbl.npsms == 0) {
- psmtbl.psms = _free(psmtbl.psms);
- psmtbl.nalloced = 0;
- }
}
return sigprocmask(SIG_SETMASK, &oldMask, NULL);
psm->child = 0;
psm->reaped = 0;
psm->status = 0;
- psm->reaper = 1;
+ psm->reaper = 0;
/* XXX FIXME: except for %verifyscript, rpmteNEVR can be used. */
xx = headerNVR(h, &n, &v, &r);
/**
*/
struct rpmpsm_s {
+ void * q_forw; /*!< for use by insque(3)/remque(3). */
+ void * q_back;
+ pid_t child; /*!< Currently running process. */
+ pid_t reaped; /*!< Reaped waitpid return. */
+ int status; /*!< Reaped waitpid status. */
+
/*@refcounted@*/
rpmts ts; /*!< transaction set */
/*@dependent@*/ /*@null@*/
rpmfi fi; /*!< transaction element file info */
FD_t cfd; /*!< Payload file handle. */
FD_t fd; /*!< Repackage file handle. */
- Header oh; /*!< Repackage/multilib header. */
+ Header oh; /*!< Repackage header. */
/*@null@*/
rpmdbMatchIterator mi;
/*@observer@*/
int chrootDone; /*!< Was chroot(2) done by pkgStage? */
int unorderedSuccessor; /*!< Can the PSM be run asynchronously? */
int reaper; /*!< Register SIGCHLD handler? */
- pid_t reaped; /*!< Reaped waitpid return. */
- pid_t child; /*!< Currently running process. */
- int status; /*!< Reaped waitpid status. */
rpmCallbackType what; /*!< Callback type. */
unsigned long amount; /*!< Callback amount. */
unsigned long total; /*!< Callback total. */
-
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
-
#include "system.h"
#include <pthread.h>
-#include <signal.h>
-#include <rpmlib.h>
-#include <rpmts.h>
-#include "psm.h"
+#include <rpmsq.h>
+#include <popt.h>
#include "debug.h"
-#define _PSM_DEBUG 0
-/*@unchecked@*/
-int _psm_debug = _PSM_DEBUG;
-
-#define SHELL_PATH "/bin/sh" /* Path of the shell. */
-#define SHELL_NAME "sh" /* Name to give it. */
-
-
-/**
- */
-/*@unchecked@*/
-static sigset_t caught;
-
-/**
- */
-/*@unchecked@*/
-static struct psmtbl_s {
- int nalloced;
- int npsms;
-/*@null@*/
- rpmpsm * psms;
-} psmtbl = { 0, 0, NULL };
-
-/* forward ref */
-static void handler(int signum)
- /*@globals caught, psmtbl, fileSystem @*/
- /*@modifies caught, psmtbl, fileSystem @*/;
-
-/**
- */
-/*@unchecked@*/
-static pthread_mutex_t satbl_lock = PTHREAD_MUTEX_INITIALIZER;
-
-/**
- */
-/*@unchecked@*/
-/*@-fullinitblock@*/
-static struct sigtbl_s {
- int signum;
- int active;
- void (*handler) (int signum);
- struct sigaction oact;
-} satbl[] = {
- { SIGINT, 0, handler },
-#define satbl_sigint (&satbl[0])
- { SIGQUIT, 0, handler },
-#define satbl_sigquit (&satbl[1])
- { SIGCHLD, 0, handler },
-#define satbl_sigchld (&satbl[2])
-#define sigchld_active satbl_sigchld->active
-#define DO_LOCK() pthread_mutex_lock(&satbl_lock);
-#define DO_UNLOCK() pthread_mutex_unlock(&satbl_lock);
-#define INIT_LOCK() \
- { pthread_mutex_init (&satbl_lock, NULL); sigchld_active = 0; }
-#define ADD_REF() sigchld_active++
-#define SUB_REF() --sigchld_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, 0, handler },
-#define satbl_sighup (&satbl[3])
- { SIGTERM, 0, handler },
-#define satbl_sigterm (&satbl[4])
- { SIGPIPE, 0, handler },
-#define satbl_sigpipe (&satbl[5])
- { -1, 0, NULL },
-};
-typedef struct sigtbl_s * sigtbl;
-/*@=fullinitblock@*/
-
-/**
- */
-/*@-incondefs@*/
-static void handler(int signum)
-{
- sigtbl tbl;
-
- for (tbl = satbl; tbl->signum >= 0; tbl++) {
- if (tbl->signum != signum)
- continue;
- if (!tbl->active)
- continue;
- (void) sigaddset(&caught, signum);
- switch (signum) {
- case SIGCHLD:
- while (1) {
- int status = 0;
- pid_t reaped = waitpid(0, &status, WNOHANG);
- int i;
-
- if (reaped <= 0)
- /*@innerbreak@*/ break;
-
- if (psmtbl.psms)
- for (i = 0; i < psmtbl.npsms; i++) {
- rpmpsm psm = psmtbl.psms[i];
- if (psm->child != reaped)
- /*@innercontinue@*/ continue;
-
-#if _PSM_DEBUG
-/*@-modfilesys@*/
-if (_psm_debug)
-fprintf(stderr, " Reap: %p[%d:%d:%d] = %p child %d\n", psmtbl.psms, i, psmtbl.npsms, psmtbl.nalloced, psm, psm->child);
-/*@=modfilesys@*/
-#endif
-
- psm->reaped = reaped;
- psm->status = status;
- /*@innerbreak@*/ break;
- }
- }
- /*@switchbreak@*/ break;
- default:
- /*@switchbreak@*/ break;
- }
- break;
- }
-}
-/*@=incondefs@*/
-
-/* The cancellation handler. */
-static void
-sigchld_cancel (void *arg)
-{
- pid_t child = *(pid_t *) arg;
- pid_t result;
- int err;
-
- err = kill(child, SIGKILL);
-
- do {
- result = waitpid(child, NULL, 0);
- } while (result == (pid_t)-1 && errno == EINTR);
-
- DO_LOCK ();
- if (SUB_REF () == 0) {
- (void) sigaction (SIGQUIT, &satbl_sigquit->oact, (struct sigaction *) NULL);
- (void) sigaction (SIGINT, &satbl_sigint->oact, (struct sigaction *) NULL);
- }
- DO_UNLOCK ();
-}
-
-/* Execute LINE as a shell command, returning its status. */
-static int
-do_system (const char *line)
-{
- int oldtype;
- int status = -1;
- pid_t pid;
- pid_t result;
- struct sigaction sa;
- sigset_t omask;
-
- sa.sa_handler = SIG_IGN;
- sa.sa_flags = 0;
- sigemptyset (&sa.sa_mask);
-
- DO_LOCK ();
- if (ADD_REF () == 0) {
- if (sigaction (SIGINT, &sa, &satbl_sigint->oact) < 0) {
- SUB_REF ();
- goto out;
- }
- if (sigaction (SIGQUIT, &sa, &satbl_sigquit->oact) < 0) {
- SUB_REF ();
- goto out_restore_sigint;
- }
- }
- DO_UNLOCK ();
-
- /* We reuse the bitmap in the 'sa' structure. */
- sigaddset (&sa.sa_mask, SIGCHLD);
- if (sigprocmask (SIG_BLOCK, &sa.sa_mask, &omask) < 0) {
- DO_LOCK ();
- if (SUB_REF () == 0)
- goto out_restore_sigquit_and_sigint;
- goto out;
- }
-
- CLEANUP_HANDLER(sigchld_cancel, &pid, &oldtype);
-
- pid = fork ();
- if (pid == (pid_t) 0) {
- /* Child side. */
- const char *new_argv[4];
- new_argv[0] = SHELL_NAME;
- new_argv[1] = "-c";
- new_argv[2] = line;
- new_argv[3] = NULL;
-
- /* Restore the signals. */
- (void) sigaction (SIGINT, &satbl_sigint->oact, NULL);
- (void) sigaction (SIGQUIT, &satbl_sigquit->oact, NULL);
- (void) sigprocmask (SIG_SETMASK, &omask, NULL);
-
- INIT_LOCK ();
-
- /* Exec the shell. */
- (void) execve (SHELL_PATH, (char *const *) new_argv, __environ);
- _exit (127);
- } else if (pid < (pid_t) 0) {
- /* The fork failed. */
- goto out;
- } else {
- /* Parent side. */
- 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 () == 0
- && (sigaction (SIGINT, &satbl_sigint->oact, NULL)
- | sigaction (SIGQUIT, &satbl_sigquit->oact, NULL)) != 0)
- || sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL) != 0)
- {
- status = -1;
- }
- goto out;
-
-out_restore_sigquit_and_sigint:
- (void) sigaction (SIGQUIT, &satbl_sigquit->oact, NULL);
-out_restore_sigint:
- (void) sigaction (SIGINT, &satbl_sigint->oact, NULL);
-out:
- DO_UNLOCK ();
- return status;
-}
-
-static int
-xsystem (const char * line)
-{
-
- if (line == NULL)
- /* Check that we have a command processor available. It might
- not be available after a chroot(), for example. */
- return do_system ("exit 0") == 0;
-
- return do_system (line);
-}
-
static void *
other_thread(void *dat)
{
- const char * s = (const char *)dat;
- return ((void *) xsystem(s));
+ const char * cmd = (const char *)dat;
+ const char ** av = NULL;
+ int ac = 0;
+ int xx = poptParseArgvString(cmd, &ac, &av);
+ if (xx)
+ return ((void *)xx);
+fprintf(stderr, "thread(%lu): pid %u %s\n", pthread_self(), getpid(), cmd);
+ return ((void *) rpmsqExecve(av));
}
int main(int argc, char *argv[])
{
pthread_t pth;
+ const char * cmd = argv[1];
- pthread_create(&pth, NULL, other_thread, "/bin/sleep 30" );
+ if (cmd == NULL)
+ cmd = "/bin/sleep 30";
+ pthread_create(&pth, NULL, other_thread, (void *)cmd);
+fprintf(stderr, " main(%lu): pid %u other(%lu)\n", pthread_self(), getpid(), pth);
sleep(2);
pthread_cancel(pth);
rpmReadConfigFiles(NULL, NULL);
ts = rpmtsCreate();
assert(ts);
+ (void) rpmtsSetRootDir(ts, "/");
rpmIncreaseVerbosity();
rpmIncreaseVerbosity();
#define _USE_COPY_LOAD /* XXX don't use DB_DBT_MALLOC (yet) */
-/*@unchecked@*/
-int _rpmdb_debug = 0;
-
#include <sys/file.h>
-#include <signal.h>
-#include <sys/signal.h>
#ifndef DYING /* XXX already in "system.h" */
/*@-noparams@*/
#include <rpmio_internal.h>
#include <rpmmacro.h>
+#include <rpmsq.h>
#include "rpmdb.h"
#include "fprint.h"
/*@access pgpDig@*/
/*@unchecked@*/
+int _rpmdb_debug = 0;
+
+/*@unchecked@*/
static int _rebuildinprogress = 0;
/*@unchecked@*/
static int _db_filter_dups = 0;
};
-/**
- */
-/*@unchecked@*/
-static sigset_t caught;
-
-/* forward ref */
-static void handler(int signum);
-
-/**
- */
-/*@unchecked@*/
-/*@-fullinitblock@*/
-static struct sigtbl_s {
- int signum;
- int active;
- void (*handler) (int signum);
- struct sigaction oact;
-} satbl[] = {
- { SIGHUP, 0, handler },
- { SIGINT, 0, handler },
- { SIGTERM, 0, handler },
- { SIGQUIT, 0, handler },
- { SIGPIPE, 0, handler },
- { -1, 0, NULL },
-};
-/*@=fullinitblock@*/
-
-/**
- */
-/*@-incondefs@*/
-static void handler(int signum)
- /*@globals caught, satbl @*/
- /*@modifies caught @*/
-{
- struct sigtbl_s * tbl;
-
- for(tbl = satbl; tbl->signum >= 0; tbl++) {
- if (tbl->signum != signum)
- continue;
- if (!tbl->active)
- continue;
- (void) sigaddset(&caught, signum);
- break;
- }
-}
-/*@=incondefs@*/
-
-/**
- * Enable all signal handlers.
- */
-static int enableSignals(void)
- /*@globals caught, satbl, fileSystem @*/
- /*@modifies caught, satbl, fileSystem @*/
-{
- sigset_t newMask, oldMask;
- struct sigtbl_s * tbl;
- struct sigaction act;
- int rc;
-
- (void) sigfillset(&newMask); /* block all signals */
- (void) sigprocmask(SIG_BLOCK, &newMask, &oldMask);
- rc = 0;
- for(tbl = satbl; tbl->signum >= 0; tbl++) {
- if (tbl->active++ > 0)
- continue;
- (void) sigdelset(&caught, tbl->signum);
- memset(&act, 0, sizeof(act));
- act.sa_handler = tbl->handler;
- rc = sigaction(tbl->signum, &act, &tbl->oact);
- if (rc) break;
- }
- return sigprocmask(SIG_SETMASK, &oldMask, NULL);
-}
-
/*@unchecked@*/
static rpmdb rpmdbRock;
static rpmdbMatchIterator rpmmiRock;
int rpmdbCheckSignals(void)
- /*@globals rpmdbRock, rpmmiRock, satbl @*/
+ /*@globals rpmdbRock, rpmmiRock @*/
/*@modifies rpmdbRock, rpmmiRock @*/
{
- struct sigtbl_s * tbl;
sigset_t newMask, oldMask;
static int terminate = 0;
(void) sigfillset(&newMask); /* block all signals */
(void) sigprocmask(SIG_BLOCK, &newMask, &oldMask);
- for(tbl = satbl; tbl->signum >= 0; tbl++) {
- if (tbl->active == 0)
- continue;
- if (sigismember(&caught, tbl->signum))
- terminate = 1;
- }
+
+ if (sigismember(&rpmsqCaught, SIGINT)
+ || sigismember(&rpmsqCaught, SIGQUIT)
+ || sigismember(&rpmsqCaught, SIGHUP)
+ || sigismember(&rpmsqCaught, SIGTERM)
+ || sigismember(&rpmsqCaught, SIGPIPE))
+ terminate = 1;
if (terminate) {
rpmdb db;
}
/**
- * Disable all signal handlers.
- */
-static int disableSignals(void)
- /*@globals satbl, fileSystem @*/
- /*@modifies satbl, fileSystem @*/
-{
- struct sigtbl_s * tbl;
- sigset_t newMask, oldMask;
- int rc;
-
- (void) sigfillset(&newMask); /* block all signals */
- (void) sigprocmask(SIG_BLOCK, &newMask, &oldMask);
- rc = 0;
- for(tbl = satbl; tbl->signum >= 0; tbl++) {
- if (--tbl->active > 0)
- continue;
- rc = sigaction(tbl->signum, &tbl->oact, NULL);
- if (rc) break;
- }
- return sigprocmask(SIG_SETMASK, &oldMask, NULL);
-}
-
-/**
* Block all signals, returning previous signal mask.
*/
static int blockSignals(/*@unused@*/ rpmdb db, /*@out@*/ sigset_t * oldMask)
- /*@globals satbl, fileSystem @*/
- /*@modifies *oldMask, satbl, fileSystem @*/
+ /*@globals rpmsigTbl, fileSystem @*/
+ /*@modifies *oldMask, rpmsigTbl, fileSystem @*/
{
- struct sigtbl_s * tbl;
sigset_t newMask;
(void) sigfillset(&newMask); /* block all signals */
(void) sigprocmask(SIG_BLOCK, &newMask, oldMask);
- for(tbl = satbl; tbl->signum >= 0; tbl++) {
- if (tbl->active == 0)
- continue;
- (void) sigdelset(&newMask, tbl->signum);
- }
+ sigdelset(&newMask, SIGINT);
+ sigdelset(&newMask, SIGQUIT);
+ sigdelset(&newMask, SIGHUP);
+ sigdelset(&newMask, SIGTERM);
+ sigdelset(&newMask, SIGPIPE);
return sigprocmask(SIG_BLOCK, &newMask, NULL);
}
/*@=usereleased@*/
exit:
- (void) disableSignals();
+ (void) rpmsqEnable(-SIGHUP, NULL);
+ (void) rpmsqEnable(-SIGINT, NULL);
+ (void) rpmsqEnable(-SIGTERM,NULL);
+ (void) rpmsqEnable(-SIGQUIT,NULL);
+ (void) rpmsqEnable(-SIGPIPE,NULL);
return rc;
}
/*@=incondefs@*/
if (db == NULL)
return 1;
- (void) enableSignals();
+ (void) rpmsqEnable(SIGHUP, NULL);
+ (void) rpmsqEnable(SIGINT, NULL);
+ (void) rpmsqEnable(SIGTERM,NULL);
+ (void) rpmsqEnable(SIGQUIT,NULL);
+ (void) rpmsqEnable(SIGPIPE,NULL);
db->db_api = _dbapi;
pkginc_HEADERS = \
argv.h fts.h \
rpmio.h rpmurl.h rpmmacro.h rpmlog.h rpmmessages.h rpmerr.h rpmpgp.h \
- ugid.h
+ rpmsq.h ugid.h
noinst_HEADERS = rpmio_internal.h
BEECRYPTLOBJS = $(shell cat $(top_builddir)/beecrypt/listobjs)
librpmio_la_SOURCES = \
argv.c digest.c fts.c macro.c \
rpmio.c rpmlog.c rpmmalloc.c \
- rpmpgp.c rpmrpc.c strcasecmp.c stubs.c url.c ugid.c
+ rpmpgp.c rpmrpc.c rpmsq.c strcasecmp.c stubs.c url.c ugid.c
librpmio_la_LDFLAGS = -release @VERSION@ \
$(top_builddir)/file/libfmagic.la \
@WITH_ZLIB_LIB@ \
--- /dev/null
+/** \ingroup rpmio
+ * \file rpmio/rpmsq.c
+ */
+
+#include "system.h"
+
+#if defined(HAVE_PTHREAD_H) && !defined(__LCLINT__)
+#include <pthread.h>
+#endif
+
+#include <rpmsq.h>
+
+#include "debug.h"
+
+/*@unchecked@*/
+static struct rpmsqElem rpmsqRock;
+/*@unchecked@*/
+rpmsq rpmsqQueue = &rpmsqRock;
+
+void Insque(void * elem, void * prev)
+{
+ if (elem != NULL)
+ insque(elem, (prev ? prev : rpmsqQueue));
+}
+
+void Remque(void * elem)
+{
+ if (elem != NULL)
+ remque(elem);
+}
+
+/*@unchecked@*/
+sigset_t rpmsqCaught;
+
+/*@unchecked@*/
+static pthread_mutex_t rpmsigTbl_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+
+/*@unchecked@*/
+/*@-fullinitblock@*/
+static struct rpmsig_s {
+ int signum;
+ void (*handler) (int signum);
+ int active;
+ struct sigaction oact;
+} rpmsigTbl[] = {
+ { SIGINT, rpmsqHandler },
+#define rpmsigTbl_sigint (&rpmsigTbl[0])
+ { SIGQUIT, rpmsqHandler },
+#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 },
+#define rpmsigTbl_sighup (&rpmsigTbl[3])
+ { SIGTERM, rpmsqHandler },
+#define rpmsigTbl_sigterm (&rpmsigTbl[4])
+ { SIGPIPE, rpmsqHandler },
+#define rpmsigTbl_sigpipe (&rpmsigTbl[5])
+ { -1, NULL },
+};
+/*@=fullinitblock@*/
+
+/**
+ */
+/*@-incondefs@*/
+void rpmsqHandler(int signum)
+{
+ rpmsig tbl;
+
+ for (tbl = rpmsigTbl; tbl->signum >= 0; tbl++) {
+ if (tbl->signum != 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;
+ }
+}
+/*@=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 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);
+ sa.sa_flags = 0;
+ sigemptyset (&sa.sa_mask);
+ sa.sa_handler = (handler != NULL ? handler : tbl->handler);
+ if (sigaction(tbl->signum, &sa, &tbl->oact) < 0) {
+ SUB_REF(tbl);
+ break;
+ }
+ }
+ } else { /* Disable. */
+ if (SUB_REF(tbl) <= 0) {
+ tbl->active = 0; /* XXX just in case */
+ if (sigaction(tbl->signum, &tbl->oact, NULL) < 0)
+ break;
+ }
+ }
+ 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;
+}
--- /dev/null
+#ifndef H_RPMSQ
+#define H_RPMSQ
+
+/** \ingroup rpmio
+ * \file rpmio/rpmsq.h
+ *
+ */
+
+#include <signal.h>
+#include <sys/signal.h>
+#include <search.h>
+
+typedef struct rpmsig_s * rpmsig;
+
+typedef struct rpmsqElem * rpmsq;
+
+/**
+ * SIGCHLD queue element.
+ */
+struct rpmsqElem {
+ struct rpmsqElem * q_forw; /*!< for use by insque(3)/remque(3). */
+ struct rpmsqElem * q_back;
+ pid_t child; /*!< Currently running child. */
+ pid_t reaped; /*!< Reaped waitpid(3) return. */
+ int status; /*!< Reaped waitpid(3) status. */
+};
+
+/*@unchecked@*/
+extern rpmsq rpmsqQueue;
+
+/*@unchecked@*/
+extern sigset_t rpmsqCaught;
+
+#ifdef __cplusplus
+{
+#endif
+
+/**
+ */
+void Insque(/*@null@*/ void * elem, /*@null@*/ void * prev)
+ /*@globals rpmsqQueue @*/
+ /*@modifies elem, rpmsqQueue @*/;
+
+/**
+ */
+void Remque(/*@null@*/ void * elem)
+ /*@modifies elem @*/;
+
+/**
+ */
+void rpmsqHandler(int signum)
+ /*@globals rpmsqCaught, fileSystem @*/
+ /*@modifies rpmsqCaught, fileSystem @*/;
+
+/**
+ * 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, fileSystem, internalState @*/
+ /*@modifies rpmsqCaught, fileSystem, internalState @*/;
+
+/**
+ * Execute a command, returning its status.
+ */
+int
+rpmsqExecve (const char ** argv)
+ /*@*/;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H_RPMSQ */