From 948d40e4829e9a6895e6b831ebcb688af849fb90 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Fri, 12 Jul 2019 16:32:45 +0200 Subject: [PATCH] Cygwin: return full sigset_t from sig_send So far sig_send's return type is int. The problem with this is that sig_send returns a sigset_t on __SIGPENDING, and sigset_t is defined as long type. So the function only returns the lower 32 bit of sigset_t, which is fine on 32 bit, but casts away the pending RT signals on 64 bit. Fix this by changing the return type of sig_send to sigset_t, so as not to narrow down the sigset when returning from handling __SIGPENDING. Make sure to cast correctly in all invocations of sig_send. Signed-off-by: Corinna Vinschen --- winsup/cygwin/fhandler_signalfd.cc | 2 +- winsup/cygwin/signal.cc | 4 ++-- winsup/cygwin/sigproc.cc | 8 ++++---- winsup/cygwin/sigproc.h | 6 +++--- winsup/cygwin/thread.cc | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/winsup/cygwin/fhandler_signalfd.cc b/winsup/cygwin/fhandler_signalfd.cc index 6c7da02e9..4d89a6c5b 100644 --- a/winsup/cygwin/fhandler_signalfd.cc +++ b/winsup/cygwin/fhandler_signalfd.cc @@ -151,7 +151,7 @@ fhandler_signalfd::write (const void *, size_t) int fhandler_signalfd::poll () { - sigset_t outset = (sigset_t) sig_send (myself, __SIGPENDING, &_my_tls); + sigset_t outset = sig_send (myself, __SIGPENDING, &_my_tls); if (outset == SIG_BAD_MASK) return -1; if ((outset & sigset) != 0) diff --git a/winsup/cygwin/signal.cc b/winsup/cygwin/signal.cc index 9c51ec129..920a533f3 100644 --- a/winsup/cygwin/signal.cc +++ b/winsup/cygwin/signal.cc @@ -264,7 +264,7 @@ _pinfo::kill (siginfo_t& si) if (si.si_signo == 0) res = 0; - else if ((res = sig_send (this, si))) + else if ((res = (int) sig_send (this, si))) { sigproc_printf ("%d = sig_send, %E ", res); res = -1; @@ -718,7 +718,7 @@ sigqueue (pid_t pid, int sig, const union sigval value) si.si_signo = sig; si.si_code = SI_QUEUE; si.si_value = value; - return sig_send (dest, si); + return (int) sig_send (dest, si); } extern "C" int diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index 3b6492bb4..cba1af785 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -422,7 +422,7 @@ _cygtls::remove_pending_sigs () extern "C" int sigpending (sigset_t *mask) { - sigset_t outset = (sigset_t) sig_send (myself, __SIGPENDING, &_my_tls); + sigset_t outset = sig_send (myself, __SIGPENDING, &_my_tls); if (outset == SIG_BAD_MASK) return -1; *mask = outset; @@ -503,7 +503,7 @@ exit_thread (DWORD res) ExitThread (res); } -int __reg3 +sigset_t __reg3 sig_send (_pinfo *p, int sig, _cygtls *tls) { siginfo_t si = {}; @@ -516,7 +516,7 @@ sig_send (_pinfo *p, int sig, _cygtls *tls) If pinfo *p == NULL, send to the current process. If sending to this process, wait for notification that a signal has completed before returning. */ -int __reg3 +sigset_t __reg3 sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls) { int rc = 1; @@ -748,7 +748,7 @@ out: if (si.si_signo != __SIGPENDING) /* nothing */; else if (!rc) - rc = (int) pending; + rc = pending; else rc = SIG_BAD_MASK; sigproc_printf ("returning %p from sending signal %d", rc, si.si_signo); diff --git a/winsup/cygwin/sigproc.h b/winsup/cygwin/sigproc.h index 9beb31dcf..a6f1428ce 100644 --- a/winsup/cygwin/sigproc.h +++ b/winsup/cygwin/sigproc.h @@ -71,8 +71,8 @@ class _pinfo; void __stdcall proc_terminate (); void __stdcall sigproc_init (); bool __reg1 pid_exists (pid_t); -int __reg3 sig_send (_pinfo *, siginfo_t&, class _cygtls * = NULL); -int __reg3 sig_send (_pinfo *, int, class _cygtls * = NULL); +sigset_t __reg3 sig_send (_pinfo *, siginfo_t&, class _cygtls * = NULL); +sigset_t __reg3 sig_send (_pinfo *, int, class _cygtls * = NULL); void __stdcall signal_fixup_after_exec (); void __stdcall sigalloc (); @@ -109,7 +109,7 @@ class lock_signals public: lock_signals () { - worked = sig_send (NULL, __SIGHOLD) == 0; + worked = (bool) sig_send (NULL, __SIGHOLD) == 0; } operator int () const { diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc index 43a6c88b3..e09507e07 100644 --- a/winsup/cygwin/thread.cc +++ b/winsup/cygwin/thread.cc @@ -3311,7 +3311,7 @@ pthread_kill (pthread_t thread, int sig) rval = ESRCH; else if (sig) { - rval = sig_send (NULL, si, thread->cygtls); + rval = (int) sig_send (NULL, si, thread->cygtls); if (rval == -1) rval = get_errno (); } @@ -3354,7 +3354,7 @@ pthread_sigqueue (pthread_t *thread, int sig, const union sigval value) si.si_value = value; si.si_pid = myself->pid; si.si_uid = myself->uid; - return sig_send (NULL, si, (*thread)->cygtls); + return (int) sig_send (NULL, si, (*thread)->cygtls); } /* ID */