diff options
Diffstat (limited to 'cpukit/posix')
-rw-r--r-- | cpukit/posix/src/psignalchecksignal.c | 16 | ||||
-rw-r--r-- | cpukit/posix/src/sigtimedwait.c | 19 |
2 files changed, 31 insertions, 4 deletions
diff --git a/cpukit/posix/src/psignalchecksignal.c b/cpukit/posix/src/psignalchecksignal.c index 1ed3bacdf7..8bba7a4226 100644 --- a/cpukit/posix/src/psignalchecksignal.c +++ b/cpukit/posix/src/psignalchecksignal.c @@ -19,6 +19,7 @@ #include <errno.h> #include <pthread.h> #include <signal.h> +#include <string.h> #include <rtems/system.h> #include <rtems/score/isr.h> @@ -46,6 +47,7 @@ bool _POSIX_signals_Check_signal( { siginfo_t siginfo_struct; sigset_t saved_signals_blocked; + Thread_Wait_information stored_thread_wait_information; if ( ! _POSIX_signals_Clear_signals( api, signo, &siginfo_struct, is_global, true ) ) @@ -73,6 +75,14 @@ bool _POSIX_signals_Check_signal( api->signals_blocked |= _POSIX_signals_Vectors[ signo ].sa_mask; /* + * We have to save the blocking information of the current wait queue + * because the signal handler may subsequently go on and put the thread + * on a wait queue, for its own purposes. + */ + memcpy( &stored_thread_wait_information, &_Thread_Executing->Wait, + sizeof( Thread_Wait_information )); + + /* * Here, the signal handler function executes */ switch ( _POSIX_signals_Vectors[ signo ].sa_flags ) { @@ -89,6 +99,12 @@ bool _POSIX_signals_Check_signal( } /* + * Restore the blocking information + */ + memcpy( &_Thread_Executing->Wait, &stored_thread_wait_information, + sizeof( Thread_Wait_information )); + + /* * Restore the previous set of blocked signals */ api->signals_blocked = saved_signals_blocked; diff --git a/cpukit/posix/src/sigtimedwait.c b/cpukit/posix/src/sigtimedwait.c index 70b632b6de..41ebf88677 100644 --- a/cpukit/posix/src/sigtimedwait.c +++ b/cpukit/posix/src/sigtimedwait.c @@ -26,7 +26,7 @@ #include <rtems/posix/time.h> #include <rtems/score/isr.h> -int _POSIX_signals_Get_highest( +int _POSIX_signals_Get_lowest( sigset_t set ) { @@ -115,7 +115,7 @@ int sigtimedwait( _ISR_Disable( level ); if ( *set & api->signals_pending ) { /* XXX real info later */ - the_info->si_signo = _POSIX_signals_Get_highest( api->signals_pending ); + the_info->si_signo = _POSIX_signals_Get_lowest( api->signals_pending ); _POSIX_signals_Clear_signals( api, the_info->si_signo, @@ -133,7 +133,7 @@ int sigtimedwait( /* Process pending signals? */ if ( *set & _POSIX_signals_Pending ) { - signo = _POSIX_signals_Get_highest( _POSIX_signals_Pending ); + signo = _POSIX_signals_Get_lowest( _POSIX_signals_Pending ); _POSIX_signals_Clear_signals( api, signo, the_info, true, false ); _ISR_Enable( level ); @@ -161,6 +161,17 @@ int sigtimedwait( */ _POSIX_signals_Clear_signals( api, the_info->si_signo, the_info, false, false ); - errno = _Thread_Executing->Wait.return_code; + + /* Set errno only if return code is not EINTR or + * if EINTR was caused by a signal being caught, which + * was not in our set. + */ + + if ( (_Thread_Executing->Wait.return_code != EINTR) + || !(*set & signo_to_mask( the_info->si_signo )) ) { + errno = _Thread_Executing->Wait.return_code; + return -1; + } + return the_info->si_signo; } |