]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Implement sigpending(). All absolutely horrible. Sigh.
authorJulian Seward <jseward@acm.org>
Wed, 19 Jun 2002 17:35:45 +0000 (17:35 +0000)
committerJulian Seward <jseward@acm.org>
Wed, 19 Jun 2002 17:35:45 +0000 (17:35 +0000)
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@443

coregrind/vg_include.h
coregrind/vg_mylibc.c
coregrind/vg_signals.c
vg_include.h
vg_mylibc.c
vg_signals.c
vg_syscall_mem.c

index bdafd3f8e6f8e60dc24da4db3c0a52cd15a7f73b..7264581a743a5b2679abdfdc1e10e9df7a616d56 100644 (file)
@@ -505,9 +505,14 @@ extern Bool  VG_(is_empty_arena) ( ArenaId aid );
 #define VG_USERREQ__GET_KEY_D_AND_S         0x3022
 
 #define VG_USERREQ__NUKE_OTHER_THREADS      0x3023
+
+/* Ask how many signal handler returns have happened to this
+   thread. */
 #define VG_USERREQ__GET_N_SIGS_RETURNED     0x3024
 
 
+
+
 /* Cosmetic ... */
 #define VG_USERREQ__GET_PTHREAD_TRACE_LEVEL 0x3101
 /* Log a pthread error from client-space.  Cosmetic. */
@@ -824,6 +829,9 @@ extern void VG_(do_pthread_sigmask_SCSS_upd) ( ThreadId tid,
 extern void VG_(send_signal_to_thread) ( ThreadId thread,
                                          Int signo );
 
+extern void VG_(do_sigpending) ( ThreadId tid, vki_ksigset_t* set );
+
+
 /* Modify the current thread's state once we have detected it is
    returning from a signal handler. */
 extern Bool VG_(signal_returns) ( ThreadId );
@@ -981,6 +989,7 @@ extern Int VG_(ksignal)(Int signum, void (*sighandler)(Int));
 extern Int VG_(ksigaltstack)( const vki_kstack_t* ss, vki_kstack_t* oss );
 
 extern Int VG_(kill)( Int pid, Int signo );
+extern Int VG_(sigpending) ( vki_ksigset_t* set );
 
 
 /* ---------------------------------------------------------------------
index 4a302a8ee4e75d74d98417be5beca4f7f4edcbcc..e32aee8d101f335636f27d76344044acf7cb101b 100644 (file)
@@ -287,6 +287,13 @@ Int VG_(kill)( Int pid, Int signo )
 }
 
 
+Int VG_(sigpending) ( vki_ksigset_t* set )
+{
+   Int res = vg_do_syscall1(__NR_sigpending, (UInt)set);
+   return VG_(is_kerror)(res) ? -1 : 0;
+}
+
+
 /* ---------------------------------------------------------------------
    mmap/munmap, exit, fcntl
    ------------------------------------------------------------------ */
index cb9d53f92bec7ff0d6bbeef63b1f058f8ce57277..439ed4c94f3c8912686267b71b18ae22f80dd20e 100644 (file)
@@ -780,6 +780,62 @@ void VG_(send_signal_to_thread) ( ThreadId thread, Int sig )
 }
 
 
+/* Store in set the signals which could be delivered to this thread
+   right now (since they are pending) but cannot be, because the
+   thread has masked them out. */
+void VG_(do_sigpending) ( ThreadId tid, vki_ksigset_t* set )
+{
+   Int           sig, res;
+   Bool          maybe_pend;
+   vki_ksigset_t process_pending;
+
+   /* Get the set of signals which are pending for the process as a
+      whole. */
+   res = VG_(sigpending)( &process_pending );
+   vg_assert(res == 0);
+
+   VG_(ksigemptyset)(set);
+   for (sig = 1; sig <= VKI_KNSIG; sig++) {
+
+      /* Figure out if the signal could be pending for this thread.
+         There are two cases. */
+      maybe_pend = False;
+
+      /* Case 1: perhaps the signal is pending for the process as a
+         whole -- that is, is blocked even valgrind's signal
+         handler. */
+      if (VG_(ksigismember)( &process_pending, sig ))
+         maybe_pend = True;
+
+      /* Case 2: the signal has been collected by our handler and is
+         now awaiting disposition inside valgrind. */
+      if (/* is it pending at all? */
+          vg_dcss.dcss_sigpending[sig]
+          && 
+         /* check it is not specifically directed to some other thread */
+          (vg_dcss.dcss_destthread[sig] == VG_INVALID_THREADID
+           || vg_dcss.dcss_destthread[sig] == tid)
+         )
+         maybe_pend = True;
+
+      if (!maybe_pend)
+         continue; /* this signal just ain't pending! */
+
+      /* Check other necessary conditions now ... */
+
+      if (VG_(ksigismember)( &VG_(threads)[tid].sigs_waited_for, sig ))
+         continue; /* tid is sigwaiting for sig, so will never be
+                      offered to a handler */
+      if (! VG_(ksigismember)( &VG_(threads)[tid].sig_mask, sig ))
+         continue; /* not blocked in this thread */
+
+      /* Ok, sig could be delivered to this thread if only it wasn't
+         masked out.  So we add it to set. */
+      VG_(ksigaddset)( set, sig );
+   }
+}
+
+
 /* ---------------------------------------------------------------------
    LOW LEVEL STUFF TO DO WITH SIGNALS: IMPLEMENTATION
    ------------------------------------------------------------------ */
index bdafd3f8e6f8e60dc24da4db3c0a52cd15a7f73b..7264581a743a5b2679abdfdc1e10e9df7a616d56 100644 (file)
@@ -505,9 +505,14 @@ extern Bool  VG_(is_empty_arena) ( ArenaId aid );
 #define VG_USERREQ__GET_KEY_D_AND_S         0x3022
 
 #define VG_USERREQ__NUKE_OTHER_THREADS      0x3023
+
+/* Ask how many signal handler returns have happened to this
+   thread. */
 #define VG_USERREQ__GET_N_SIGS_RETURNED     0x3024
 
 
+
+
 /* Cosmetic ... */
 #define VG_USERREQ__GET_PTHREAD_TRACE_LEVEL 0x3101
 /* Log a pthread error from client-space.  Cosmetic. */
@@ -824,6 +829,9 @@ extern void VG_(do_pthread_sigmask_SCSS_upd) ( ThreadId tid,
 extern void VG_(send_signal_to_thread) ( ThreadId thread,
                                          Int signo );
 
+extern void VG_(do_sigpending) ( ThreadId tid, vki_ksigset_t* set );
+
+
 /* Modify the current thread's state once we have detected it is
    returning from a signal handler. */
 extern Bool VG_(signal_returns) ( ThreadId );
@@ -981,6 +989,7 @@ extern Int VG_(ksignal)(Int signum, void (*sighandler)(Int));
 extern Int VG_(ksigaltstack)( const vki_kstack_t* ss, vki_kstack_t* oss );
 
 extern Int VG_(kill)( Int pid, Int signo );
+extern Int VG_(sigpending) ( vki_ksigset_t* set );
 
 
 /* ---------------------------------------------------------------------
index 4a302a8ee4e75d74d98417be5beca4f7f4edcbcc..e32aee8d101f335636f27d76344044acf7cb101b 100644 (file)
@@ -287,6 +287,13 @@ Int VG_(kill)( Int pid, Int signo )
 }
 
 
+Int VG_(sigpending) ( vki_ksigset_t* set )
+{
+   Int res = vg_do_syscall1(__NR_sigpending, (UInt)set);
+   return VG_(is_kerror)(res) ? -1 : 0;
+}
+
+
 /* ---------------------------------------------------------------------
    mmap/munmap, exit, fcntl
    ------------------------------------------------------------------ */
index cb9d53f92bec7ff0d6bbeef63b1f058f8ce57277..439ed4c94f3c8912686267b71b18ae22f80dd20e 100644 (file)
@@ -780,6 +780,62 @@ void VG_(send_signal_to_thread) ( ThreadId thread, Int sig )
 }
 
 
+/* Store in set the signals which could be delivered to this thread
+   right now (since they are pending) but cannot be, because the
+   thread has masked them out. */
+void VG_(do_sigpending) ( ThreadId tid, vki_ksigset_t* set )
+{
+   Int           sig, res;
+   Bool          maybe_pend;
+   vki_ksigset_t process_pending;
+
+   /* Get the set of signals which are pending for the process as a
+      whole. */
+   res = VG_(sigpending)( &process_pending );
+   vg_assert(res == 0);
+
+   VG_(ksigemptyset)(set);
+   for (sig = 1; sig <= VKI_KNSIG; sig++) {
+
+      /* Figure out if the signal could be pending for this thread.
+         There are two cases. */
+      maybe_pend = False;
+
+      /* Case 1: perhaps the signal is pending for the process as a
+         whole -- that is, is blocked even valgrind's signal
+         handler. */
+      if (VG_(ksigismember)( &process_pending, sig ))
+         maybe_pend = True;
+
+      /* Case 2: the signal has been collected by our handler and is
+         now awaiting disposition inside valgrind. */
+      if (/* is it pending at all? */
+          vg_dcss.dcss_sigpending[sig]
+          && 
+         /* check it is not specifically directed to some other thread */
+          (vg_dcss.dcss_destthread[sig] == VG_INVALID_THREADID
+           || vg_dcss.dcss_destthread[sig] == tid)
+         )
+         maybe_pend = True;
+
+      if (!maybe_pend)
+         continue; /* this signal just ain't pending! */
+
+      /* Check other necessary conditions now ... */
+
+      if (VG_(ksigismember)( &VG_(threads)[tid].sigs_waited_for, sig ))
+         continue; /* tid is sigwaiting for sig, so will never be
+                      offered to a handler */
+      if (! VG_(ksigismember)( &VG_(threads)[tid].sig_mask, sig ))
+         continue; /* not blocked in this thread */
+
+      /* Ok, sig could be delivered to this thread if only it wasn't
+         masked out.  So we add it to set. */
+      VG_(ksigaddset)( set, sig );
+   }
+}
+
+
 /* ---------------------------------------------------------------------
    LOW LEVEL STUFF TO DO WITH SIGNALS: IMPLEMENTATION
    ------------------------------------------------------------------ */
index 2f70c454d1d610e0b8fa980ea35596e272ec9a8e..ae80146bd84da51d9d5f4bbe105244cd2416a718 100644 (file)
@@ -3096,6 +3096,26 @@ void VG_(perform_assumed_nonblocking_syscall) ( ThreadId tid )
             make_readable( arg3, sizeof(vki_ksigset_t));
          break;
 
+      case __NR_sigpending: /* syscall 73 */
+#     if defined(__NR_rt_sigpending)
+      case __NR_rt_sigpending: /* syscall 176 */
+#     endif
+         /* int sigpending( sigset_t *set ) ; */
+         if (VG_(clo_trace_syscalls))
+            VG_(printf)( "sigpending ( %p )\n", arg1 );
+         must_be_writable( tst, "sigpending(set)", 
+                           arg1, sizeof(vki_ksigset_t));
+#        if SIGNAL_SIMULATION
+         VG_(do_sigpending)( tid, (vki_ksigset_t*)arg1 );
+         res = 0;
+        SET_EAX(tid, res);
+#        else
+         KERNEL_DO_SYSCALL(tid, res);
+#        endif
+         if ( !VG_( is_kerror )( res ) && res == 0 )
+            make_readable( arg1, sizeof( vki_ksigset_t ) ) ;
+         break ;
+
       default:
          VG_(message)
             (Vg_DebugMsg,"FATAL: unhandled syscall: %d",syscallno);