Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Faylor <me@cgf.cx>2001-01-27 05:23:46 +0300
committerChristopher Faylor <me@cgf.cx>2001-01-27 05:23:46 +0300
commit206a8d884b0386bb0b88872f8a044835897074f4 (patch)
treea6c144ea202e9580cb934124897a20af1f8a0f8c /winsup/cygwin/exceptions.cc
parent7646d1a111e689ba2f25fcc26de9a1668547de8a (diff)
* exceptions.cc (sigreturn): Call any pending signals prior to resetting the
signal mask so that stacked signals behave correctly. (sigdelayed): Avoid a race where a signal could end up calling an incorrect signal handler if two signals come in close together.
Diffstat (limited to 'winsup/cygwin/exceptions.cc')
-rw-r--r--winsup/cygwin/exceptions.cc29
1 files changed, 20 insertions, 9 deletions
diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc
index 9a51f49f1..f3135843b 100644
--- a/winsup/cygwin/exceptions.cc
+++ b/winsup/cygwin/exceptions.cc
@@ -653,7 +653,6 @@ interrupt_setup (int sig, void *handler, DWORD retaddr, DWORD *retaddr_on_stack,
{
sigsave.retaddr = retaddr;
sigsave.retaddr_on_stack = retaddr_on_stack;
- sigsave.oldmask = myself->getsigmask (); // Remember for restoration
/* FIXME: Not multi-thread aware */
sigsave.newmask = myself->getsigmask () | siga.sa_mask | SIGTOMASK (sig);
sigsave.sa_flags = siga.sa_flags;
@@ -738,9 +737,9 @@ set_sig_errno (int e)
// sigproc_printf ("errno %d", e);
}
-static int call_handler (int, void *, struct sigaction&) __attribute__((regparm(3)));
+static int setup_handler (int, void *, struct sigaction&) __attribute__((regparm(3)));
static int
-call_handler (int sig, void *handler, struct sigaction& siga)
+setup_handler (int sig, void *handler, struct sigaction& siga)
{
CONTEXT cx;
bool interrupted = 0;
@@ -860,7 +859,7 @@ set_pending:
#endif /* i386 */
#ifndef HAVE_CALL_HANDLER
-#error "Need to supply machine dependent call_handler"
+#error "Need to supply machine dependent setup_handler"
#endif
/* Keyboard interrupt handler. */
@@ -1000,7 +999,7 @@ stop:
dosig:
/* Dispatch to the appropriate function. */
sigproc_printf ("signal %d, about to call %p", sig, handler);
- rc = call_handler (sig, handler, thissig);
+ rc = setup_handler (sig, handler, thissig);
done:
sigproc_printf ("returning %d", rc);
@@ -1123,13 +1122,23 @@ _sigreturn:
addl $4,%%esp # Remove argument
movl %%esp,%%ebp
addl $36,%%ebp
- call _set_process_mask@4
+
+ cmpl $0,%4 # Did a signal come in?
+ jz 1f # No, if zero
+ call _call_signal_handler@0 # yes handle the signal
+
+# FIXME: There is a race here. The signal handler could set up
+# the sigsave structure between _call_signal_handler and the
+# end of _set_process_mask. This would make cygwin detect an
+# incorrect signal mask.
+
+1: call _set_process_mask@4
popl %%eax # saved errno
testl %%eax,%%eax # Is it < 0
- jl 1f # yup. ignore it
+ jl 2f # yup. ignore it
movl %1,%%ebx
movl %%eax,(%%ebx)
-1: popl %%eax
+2: popl %%eax
popl %%ebx
popl %%ecx
popl %%edx
@@ -1158,11 +1167,13 @@ _sigdelayed0:
pushl $_sigreturn
call _reset_signal_arrived@0
+ pushl %5
movl $0,%0
pushl %8
call _set_process_mask@4
- jmp *%5
+ popl %%eax
+ jmp *%%eax
__no_sig_end:
" : "=m" (sigsave.sig) : "m" (&_impure_ptr->_errno),