Sanity.
authorjbj <devnull@localhost>
Sat, 15 Mar 2003 21:51:11 +0000 (21:51 +0000)
committerjbj <devnull@localhost>
Sat, 15 Mar 2003 21:51:11 +0000 (21:51 +0000)
CVS patchset: 6692
CVS date: 2003/03/15 21:51:11

lib/Makefile.am
lib/psm.c
lib/tsystem.c

index d38aab2..bea82b1 100644 (file)
@@ -100,6 +100,9 @@ trb: trb.o librpm.la
 tthread: tthread.o librpm.la
        $(LINK) $(CFLAGS) $(DEFS) $(INCLUDES) -o $@ $< $(mylibs) @WITH_LIBELF_LIB@
 
+tsystem: tsystem.o
+       $(LINK) $(CFLAGS) $(DEFS) $(INCLUDES) -o $@ $< -L/lib/tls -lpthread
+
 tplatform: tplatform.o librpm.la
        $(LINK) @LDFLAGS_STATIC@ $(CFLAGS) $(DEFS) $(INCLUDES) -o $@ $< $(mylibs)
 
index 72ecb67..ba19f7b 100644 (file)
--- a/lib/psm.c
+++ b/lib/psm.c
@@ -797,7 +797,7 @@ static rpmRC runScript(rpmpsm psm, Header h, const char * sln,
     psm->child = 0;
     psm->reaped = 0;
     psm->status = 0;
-    psm->reaper = 0;
+    psm->reaper = 1;
 
     /* XXX FIXME: except for %verifyscript, rpmteNEVR can be used. */
     xx = headerNVR(h, &n, &v, &r);
index 14b0636..dffa220 100644 (file)
    02111-1307 USA.  */
 
 #include <sched.h>
+#include <pthread.h>
+
 #include <signal.h>
-#include <sysdep.h>
 #include <unistd.h>
+#include <sys/syscall.h>
 #include <sys/wait.h>
-#include <bits/libc-lock.h>
-#include <kernel-features.h>
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+
+#define        SHELL_PATH      "/bin/sh"       /* Path of the shell.  */
+#define        SHELL_NAME      "sh"            /* Name to give it.  */
+
+static struct sigaction intr;
+static struct sigaction quit;
+
+static int syssa_refcnt;
+
+static pthread_mutex_t syssa_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* =============================================================== */
+
+/* We need some help from the assembler to generate optimal code.  We
+   define some macros here which later will be used.  */
+asm (".L__X'%ebx = 1\n\t"
+     ".L__X'%ecx = 2\n\t"
+     ".L__X'%edx = 2\n\t"
+     ".L__X'%eax = 3\n\t"
+     ".L__X'%esi = 3\n\t"
+     ".L__X'%edi = 3\n\t"
+     ".L__X'%ebp = 3\n\t"
+     ".L__X'%esp = 3\n\t"
+     ".macro bpushl name reg\n\t"
+     ".if 1 - \\name\n\t"
+     ".if 2 - \\name\n\t"
+     "pushl %ebx\n\t"
+     ".else\n\t"
+     "xchgl \\reg, %ebx\n\t"
+     ".endif\n\t"
+     ".endif\n\t"
+     ".endm\n\t"
+     ".macro bpopl name reg\n\t"
+     ".if 1 - \\name\n\t"
+     ".if 2 - \\name\n\t"
+     "popl %ebx\n\t"
+     ".else\n\t"
+     "xchgl \\reg, %ebx\n\t"
+     ".endif\n\t"
+     ".endif\n\t"
+     ".endm\n\t"
+     ".macro bmovl name reg\n\t"
+     ".if 1 - \\name\n\t"
+     ".if 2 - \\name\n\t"
+     "movl \\reg, %ebx\n\t"
+     ".endif\n\t"
+     ".endif\n\t"
+     ".endm\n\t");
+
+/* Define a macro which expands inline into the wrapper code for a system
+   call.  */
+#undef INLINE_SYSCALL
+#define INLINE_SYSCALL(name, nr, args...) \
+  ({                                                                         \
+    unsigned int resultvar = INTERNAL_SYSCALL (name, , nr, args);            \
+    if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (resultvar, ), 0))        \
+      {                                                                              \
+       errno = (INTERNAL_SYSCALL_ERRNO (resultvar, ));                       \
+       resultvar = 0xffffffff;                                               \
+      }                                                                              \
+    (int) resultvar; })
+
+/* Define a macro which expands inline into the wrapper code for a system
+   call.  This use is for internal calls that do not need to handle errors
+   normally.  It will never touch errno.  This returns just what the kernel
+   gave back.  */
+# define INTERNAL_SYSCALL(name, err, nr, args...) \
+  ({                                                                         \
+    unsigned int resultvar;                                                  \
+    asm volatile (                                                           \
+    LOADARGS_##nr                                                            \
+    "movl %1, %%eax\n\t"                                                     \
+    "int $0x80\n\t"                                                  \
+    RESTOREARGS_##nr                                                         \
+    : "=a" (resultvar)                                                       \
+    : "i" (__NR_##name) ASMFMT_##nr(args) : "memory", "cc");                 \
+    (int) resultvar; })
+
+#undef INTERNAL_SYSCALL_DECL
+#define INTERNAL_SYSCALL_DECL(err) do { } while (0)
+
+#undef INTERNAL_SYSCALL_ERROR_P
+#define INTERNAL_SYSCALL_ERROR_P(val, err) \
+  ((unsigned int) (val) >= 0xfffff001u)
+
+#undef INTERNAL_SYSCALL_ERRNO
+#define INTERNAL_SYSCALL_ERRNO(val, err)       (-(val))
+
+#define LOADARGS_0
+# define LOADARGS_1 \
+    "bpushl .L__X'%k3, %k3\n\t"                                                      \
+    "bmovl .L__X'%k3, %k3\n\t"
+#define LOADARGS_2     LOADARGS_1
+#define LOADARGS_3     LOADARGS_1
+#define LOADARGS_4     LOADARGS_1
+#define LOADARGS_5     LOADARGS_1
+
+#define RESTOREARGS_0
+# define RESTOREARGS_1 \
+    "bpopl .L__X'%k3, %k3\n\t"
+#define RESTOREARGS_2  RESTOREARGS_1
+#define RESTOREARGS_3  RESTOREARGS_1
+#define RESTOREARGS_4  RESTOREARGS_1
+#define RESTOREARGS_5  RESTOREARGS_1
+
+#define ASMFMT_0()
+#define ASMFMT_1(arg1) \
+       , "acdSD" (arg1)
+#define ASMFMT_2(arg1, arg2) \
+       , "adSD" (arg1), "c" (arg2)
+#define ASMFMT_3(arg1, arg2, arg3) \
+       , "aSD" (arg1), "c" (arg2), "d" (arg3)
+#define ASMFMT_4(arg1, arg2, arg3, arg4) \
+       , "aD" (arg1), "c" (arg2), "d" (arg3), "S" (arg4)
+#define ASMFMT_5(arg1, arg2, arg3, arg4, arg5) \
+       , "a" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5)
 
 /* We have to and actually can handle cancelable system().  The big
    problem: we have to kill the child process if necessary.  To do
    return.  It might still be in the kernel when the cancellation
    request comes.  Therefore we have to use the clone() calls ability
    to have the kernel write the PID into the user-level variable.  */
-#ifdef __ASSUME_CLONE_THREAD_FLAGS
 # define FORK() \
   INLINE_SYSCALL (clone, 3, CLONE_PARENT_SETTID | SIGCHLD, 0, &pid)
-#endif
+
+/* =============================================================== */
 
 /* The cancellation handler.  */
 static void
 cancel_handler (void *arg)
 {
   pid_t child = *(pid_t *) arg;
+  pid_t result;
+  int err;
 
-  INTERNAL_SYSCALL_DECL (err);
-  INTERNAL_SYSCALL (kill, err, 2, child, SIGKILL);
-
-  TEMP_FAILURE_RETRY (__waitpid (child, NULL, 0));
+  err = kill(child, SIGKILL);
 
-  DO_LOCK ();
-
-  if (SUB_REF () == 0)
-    {
-      (void) __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
-      (void) __sigaction (SIGINT, &intr, (struct sigaction *) NULL);
-    }
+  do {
+    result = waitpid(child, NULL, 0);
+  } while (result == (pid_t)-1 && errno == EINTR);
 
-  DO_UNLOCK ();
+  pthread_mutex_lock(&syssa_lock);
+  if (--syssa_refcnt == 0) {
+      (void) sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
+      (void) sigaction (SIGINT, &intr, (struct sigaction *) NULL);
+  }
+  pthread_mutex_unlock(&syssa_lock);
 }
 
-#define CLEANUP_HANDLER \
-  __libc_cleanup_region_start (1, cancel_handler, &pid)
-
-#define CLEANUP_RESET \
-  __libc_cleanup_region_end (0)
-
-
-/* Copyright (C) 1991-2000, 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 <errno.h>
-#include <signal.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <bits/libc-lock.h>
-#include <sysdep-cancel.h>
-
-
-#ifndef        HAVE_GNU_LD
-#define        __environ       environ
-#endif
-
-#define        SHELL_PATH      "/bin/sh"       /* Path of the shell.  */
-#define        SHELL_NAME      "sh"            /* Name to give it.  */
-
-
-#ifdef _LIBC_REENTRANT
-static struct sigaction intr, quit;
-static int sa_refcntr;
-__libc_lock_define_initialized (static, lock);
-
-# define DO_LOCK() __libc_lock_lock (lock)
-# define DO_UNLOCK() __libc_lock_unlock (lock)
-# define INIT_LOCK() ({ __libc_lock_init (lock); sa_refcntr = 0; })
-# define ADD_REF() sa_refcntr++
-# define SUB_REF() --sa_refcntr
-#else
-# define DO_LOCK()
-# define DO_UNLOCK()
-# define INIT_LOCK()
-# define ADD_REF() 0
-# define SUB_REF() 0
-#endif
-
-
 /* Execute LINE as a shell command, returning its status.  */
 static int
 do_system (const char *line)
 {
-  int status, save;
+  int oldtype;
+  int status;
+  int save;
   pid_t pid;
+  pid_t result;
   struct sigaction sa;
-#ifndef _LIBC_REENTRANT
-  struct sigaction intr, quit;
-#endif
   sigset_t omask;
 
+fprintf(stderr, "*** %s(%p) %s\n", __FUNCTION__, line, line);
   sa.sa_handler = SIG_IGN;
   sa.sa_flags = 0;
-  __sigemptyset (&sa.sa_mask);
-
-  DO_LOCK ();
-  if (ADD_REF () == 0)
-    {
-      if (__sigaction (SIGINT, &sa, &intr) < 0)
-       {
-         SUB_REF ();
+  sigemptyset (&sa.sa_mask);
+
+  pthread_mutex_lock(&syssa_lock);
+  if (syssa_refcnt++ == 0) {
+      if (sigaction (SIGINT, &sa, &intr) < 0) {
+         --syssa_refcnt;
          goto out;
-       }
-      if (__sigaction (SIGQUIT, &sa, &quit) < 0)
-       {
+      }
+      if (sigaction (SIGQUIT, &sa, &quit) < 0) {
          save = errno;
-         SUB_REF ();
+         --syssa_refcnt;
          goto out_restore_sigint;
-       }
-    }
-  DO_UNLOCK ();
+      }
+  }
+  pthread_mutex_unlock(&syssa_lock);
 
   /* We reuse the bitmap in the 'sa' structure.  */
-  __sigaddset (&sa.sa_mask, SIGCHLD);
+  sigaddset (&sa.sa_mask, SIGCHLD);
   save = errno;
-  if (__sigprocmask (SIG_BLOCK, &sa.sa_mask, &omask) < 0)
-    {
-#ifndef _LIBC
-      if (errno == ENOSYS)
-       __set_errno (save);
-      else
-#endif
-       {
-         DO_LOCK ();
-         if (SUB_REF () == 0)
+  if (sigprocmask (SIG_BLOCK, &sa.sa_mask, &omask) < 0) {
+          pthread_mutex_lock(&syssa_lock);
+         if (--syssa_refcnt == 0)
            {
              save = errno;
-             (void) __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
+             (void) sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
            out_restore_sigint:
-             (void) __sigaction (SIGINT, &intr, (struct sigaction *) NULL);
-             __set_errno (save);
+             (void) sigaction (SIGINT, &intr, (struct sigaction *) NULL);
+             errno = save;
            }
        out:
-         DO_UNLOCK ();
+          pthread_mutex_unlock(&syssa_lock);
          return -1;
-       }
     }
 
-#ifdef CLEANUP_HANDLER
-  CLEANUP_HANDLER;
-#endif
+  pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
+  pthread_cleanup_push(cancel_handler, &pid);
+
+/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
+             pid_t *tid, struct user_desc *tls); */
+/* INLINE_SYSCALL (clone, 3, CLONE_PARENT_SETTID | SIGCHLD, 0, &pid) */
+
+/* pid = clone(sub, NULL, (CLONE_PARENT_SETTID | SIGCHLD), line,
+               &pid???, &tls???); */
 
-#ifdef FORK
   pid = FORK ();
-#else
-  pid = __fork ();
-#endif
-  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, &intr, (struct sigaction *) NULL);
-      (void) __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
-      (void) __sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL);
-      INIT_LOCK ();
-
-      /* Exec the shell.  */
-      (void) __execve (SHELL_PATH, (char *const *) new_argv, __environ);
-      _exit (127);
-    }
-  else if (pid < (pid_t) 0)
+  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, &intr, (struct sigaction *) NULL);
+    (void) sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
+    (void) sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL);
+
+    { pthread_mutex_init (&syssa_lock, NULL); syssa_refcnt = 0; }
+
+    /* Exec the shell.  */
+    (void) execve (SHELL_PATH, (char *const *) new_argv, __environ);
+    _exit (127);
+  } else if (pid < (pid_t) 0) {
     /* The fork failed.  */
     status = -1;
-  else
+  } else {
     /* Parent side.  */
-    {
-#ifdef NO_WAITPID
-      pid_t child;
-      do
-       {
-         child = __wait (&status);
-         if (child <= -1 && errno != EINTR)
-           {
-             status = -1;
-             break;
-           }
-         /* Note that pid cannot be <= -1 and therefore the loop continues
-            when __wait returned with EINTR.  */
-       }
-      while (child != pid);
-#else
-      if (TEMP_FAILURE_RETRY (__waitpid (pid, &status, 0)) != pid)
-       status = -1;
-#endif
-    }
+    do {
+      result = waitpid(pid, &status, 0);
+    } while (result == (pid_t)-1 && errno == EINTR);
+    if (result != pid)
+      status = -1;
+  }
 
-#ifdef CLEANUP_HANDLER
-  CLEANUP_RESET;
-#endif
+  pthread_cleanup_pop(0);
+  pthread_setcanceltype (oldtype, &oldtype);
 
   save = errno;
-  DO_LOCK ();
-  if ((SUB_REF () == 0
-       && (__sigaction (SIGINT, &intr, (struct sigaction *) NULL)
-          | __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL)) != 0)
-      || __sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL) != 0)
-    {
-#ifndef _LIBC
-      /* glibc cannot be used on systems without waitpid.  */
-      if (errno == ENOSYS)
-       __set_errno (save);
-      else
-#endif
+  pthread_mutex_lock(&syssa_lock);
+  if ((--syssa_refcnt == 0
+       && (sigaction (SIGINT, &intr, (struct sigaction *) NULL)
+          | sigaction (SIGQUIT, &quit, (struct sigaction *) NULL)) != 0)
+      || sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL) != 0)
+  {
        status = -1;
-    }
-  DO_UNLOCK ();
+  }
+  pthread_mutex_unlock(&syssa_lock);
 
   return status;
 }
 
-int
-__libc_system (const char *line)
+static int
+system (const char * line)
 {
+
+fprintf(stderr, "*** %s(%p) %s\n", __FUNCTION__, line, 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;
 
-  if (SINGLE_THREAD_P)
-    return do_system (line);
+  return do_system (line);
+}
+
+static void *
+other_thread(void *dat)
+{
+    const char * s = (const char *)dat;
+fprintf(stderr, "*** %s(%p)\n", __FUNCTION__, dat);
+    return ((void *) system(s));
+}
 
-  int oldtype = LIBC_CANCEL_ASYNC ();
+int main(int argc, char *argv[])
+{
+  pthread_t pth;
 
-  int result = do_system (line);
+  pthread_create(&pth, NULL, other_thread, "/bin/pwd" );
 
-  LIBC_CANCEL_RESET (oldtype);
+  pthread_join(pth, NULL);
 
-  return result;
+  return 0;
 }
-weak_alias (__libc_system, system)
+