From: Julian Seward Date: Wed, 19 Jun 2002 17:35:45 +0000 (+0000) Subject: Implement sigpending(). All absolutely horrible. Sigh. X-Git-Tag: svn/VALGRIND_1_0_3~45 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b264e50980d6b232200ea21144c404043ef76c33;p=thirdparty%2Fvalgrind.git Implement sigpending(). All absolutely horrible. Sigh. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@443 --- diff --git a/coregrind/vg_include.h b/coregrind/vg_include.h index bdafd3f8e6..7264581a74 100644 --- a/coregrind/vg_include.h +++ b/coregrind/vg_include.h @@ -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 ); /* --------------------------------------------------------------------- diff --git a/coregrind/vg_mylibc.c b/coregrind/vg_mylibc.c index 4a302a8ee4..e32aee8d10 100644 --- a/coregrind/vg_mylibc.c +++ b/coregrind/vg_mylibc.c @@ -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 ------------------------------------------------------------------ */ diff --git a/coregrind/vg_signals.c b/coregrind/vg_signals.c index cb9d53f92b..439ed4c94f 100644 --- a/coregrind/vg_signals.c +++ b/coregrind/vg_signals.c @@ -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 ------------------------------------------------------------------ */ diff --git a/vg_include.h b/vg_include.h index bdafd3f8e6..7264581a74 100644 --- a/vg_include.h +++ b/vg_include.h @@ -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 ); /* --------------------------------------------------------------------- diff --git a/vg_mylibc.c b/vg_mylibc.c index 4a302a8ee4..e32aee8d10 100644 --- a/vg_mylibc.c +++ b/vg_mylibc.c @@ -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 ------------------------------------------------------------------ */ diff --git a/vg_signals.c b/vg_signals.c index cb9d53f92b..439ed4c94f 100644 --- a/vg_signals.c +++ b/vg_signals.c @@ -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 ------------------------------------------------------------------ */ diff --git a/vg_syscall_mem.c b/vg_syscall_mem.c index 2f70c454d1..ae80146bd8 100644 --- a/vg_syscall_mem.c +++ b/vg_syscall_mem.c @@ -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);