Index: exceptions.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/exceptions.cc,v retrieving revision 1.151 diff -u -p -r1.151 exceptions.cc --- exceptions.cc 26 Jul 2003 04:53:59 -0000 1.151 +++ exceptions.cc 18 Aug 2003 23:56:49 -0000 @@ -703,6 +703,8 @@ interrupt_setup (int sig, void *handler, } /* Clear any waiting threads prior to dispatching to handler function */ proc_subproc (PROC_CLEARWAIT, 1); + set_process_mask (sigsave.newmask); + InterlockedDecrement (myself->getsigtodo (sig)); int res = SetEvent (signal_arrived); // For an EINTR case sigproc_printf ("armed signal_arrived %p, res %d", signal_arrived, res); } @@ -903,10 +905,6 @@ setup_handler (int sig, void *handler, s } else { - pending_signals = 1; /* FIXME: Probably need to be more tricky here */ - sig_set_pending (sig); - sig_dispatch_pending (1); - low_priority_sleep (SLEEP_0_STAY_LOW); /* Hopefully, other process will be waking up soon. */ sigproc_printf ("couldn't send signal %d", sig); } @@ -990,7 +988,7 @@ set_process_mask (sigset_t newmask) sigproc_printf ("old mask = %x, new mask = %x", myself->getsigmask (), newmask); myself->setsigmask (newmask); // Set a new mask mask_sync->release (); - if (oldmask != newmask && GetCurrentThreadId () != sigtid) + if (((oldmask ^ newmask) & oldmask) && GetCurrentThreadId () != sigtid) sig_dispatch_pending (); else sigproc_printf ("not calling sig_dispatch_pending. sigtid %p current %p", @@ -1001,7 +999,7 @@ set_process_mask (sigset_t newmask) int __stdcall sig_handle (int sig, bool thisproc) { - int rc = 0; + int rc = -1; sigproc_printf ("signal %d", sig); @@ -1221,7 +1219,8 @@ unused_sig_wrapper () { /* Signal cleanup stuff. Cleans up stack (too bad that we didn't prototype signal handlers as __stdcall), calls _set_process_mask - to restore any mask, restores any potentially clobbered registers + to restore any mask. If a new signal occurs after mask restoral, + handles it. Otherwise restores any potentially clobbered registers and returns to original caller. */ __asm__ volatile ("\n\ .text \n\ @@ -1233,8 +1232,11 @@ _sigreturn: \n\ \n\ cmpl $0,%4 # Did a signal come in? \n\ jz 1f # No, if zero \n\ - call _call_signal_handler_now@0 # yes handle the signal \n\ - \n\ + movl %2,%%eax \n\ + movl %%eax,4(%%ebp) # Restore return address \n\ + subl $32,%%ebp \n\ + movl %%ebp,%%esp \n\ + jmp 3f \n\ 1: popl %%eax # saved errno \n\ testl %%eax,%%eax # Is it < 0 \n\ jl 2f # yup. ignore it \n\ @@ -1264,24 +1266,22 @@ _sigdelayed0: \n\ pushl %%ebx \n\ pushl %%eax \n\ pushl %6 # saved errno \n\ +3: \n\ pushl %3 # oldmask \n\ pushl %4 # signal argument \n\ pushl $_sigreturn \n\ \n\ call _reset_signal_arrived@0 \n\ - pushl %5 # signal number \n\ - pushl %7 # newmask \n\ + pushl %5 # signal handler \n\ movl $0,%0 # zero the signal number as a \n\ # flag to the signal handler thread\n\ # that it is ok to set up sigsave\n\ - \n\ - call _set_process_mask@4 \n\ popl %%eax \n\ jmp *%%eax \n\ __no_sig_end: \n\ " : "=m" (sigsave.sig): "X" ((char *) &_impure_ptr->_errno), "g" (sigsave.retaddr), "g" (sigsave.oldmask), "g" (sigsave.sig), - "g" (sigsave.func), "g" (sigsave.saved_errno), "g" (sigsave.newmask) + "g" (sigsave.func), "g" (sigsave.saved_errno) ); } } Index: sigproc.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/sigproc.cc,v retrieving revision 1.137 diff -u -p -r1.137 sigproc.cc --- sigproc.cc 16 Jun 2003 03:24:12 -0000 1.137 +++ sigproc.cc 18 Aug 2003 23:56:51 -0000 @@ -706,6 +706,11 @@ sig_send (_pinfo *p, int sig, DWORD ebp, */ (void) InterlockedIncrement (p->getsigtodo (sig)); + /* Force other threads to serialize in sig_dispatch_pending. + */ + if (its_me) + pending_signals = 1; + /* Notify the process that a signal has arrived. */ SetLastError (0); @@ -786,15 +791,6 @@ out: return rc; } -/* Set pending signal from the sigtodo array - */ -void __stdcall -sig_set_pending (int sig) -{ - (void) InterlockedIncrement (myself->getsigtodo (sig)); - return; -} - /* Initialize the wait_subproc thread. * Called from fork() or spawn() to initialize the handling of subprocesses. */ @@ -1102,12 +1098,23 @@ wait_sig (VOID *self) sigtid = GetCurrentThreadId (); HANDLE catchem[] = {sigcatch_main, sigcatch_nonmain, sigcatch_nosync}; + bool saw_failed_interrupt = false; sigproc_printf ("Ready. dwProcessid %d", myself->dwProcessId); for (;;) { DWORD rc = WaitForMultipleObjects (3, catchem, FALSE, sig_loop_wait); - (void) SetThreadPriority (GetCurrentThread (), WAIT_SIG_PRIORITY); + if (saw_failed_interrupt) + { + /* Give a chance and retry. + If rc is from sigcatch_main the main thread is probably running */ + if (rc > WAIT_OBJECT_0 && rc < WAIT_OBJECT_0 + MAXIMUM_WAIT_OBJECTS) + low_priority_sleep (SLEEP_0_STAY_LOW); /* Hopefully, other process will be waking up soon. */ + saw_failed_interrupt = false; + } + + (void) SetThreadPriority (GetCurrentThread (), WAIT_SIG_PRIORITY); + /* sigproc_terminate sets sig_loop_wait to zero to indicate that * this thread should terminate. */ @@ -1127,16 +1134,17 @@ wait_sig (VOID *self) } rc -= WAIT_OBJECT_0; - sigproc_printf ("awake"); + sigproc_printf ("awake %d", rc); /* A sigcatch semaphore has been signaled. Scan the sigtodo * array looking for any unprocessed signals. */ pending_signals = -1; int saw_pending_signals = 0; int saw_sigchld = 0; + for (int sig = -__SIGOFFSET; sig < NSIG; sig++) { - while (InterlockedDecrement (myself->getsigtodo (sig)) >= 0) + while (*myself->getsigtodo (sig) > 0) /* No interlock needed */ { if (sig == SIGCHLD) saw_sigchld = 1; @@ -1146,12 +1154,13 @@ wait_sig (VOID *self) main_vfork->pid || (sig != SIGCONT && ISSTATE (myself, PID_STOPPED)))) { + saw_pending_signals = 1; sigproc_printf ("signal %d blocked", sig); break; } /* Found a signal to process */ - sigproc_printf ("processing signal %d", sig); + sigproc_printf ("processing signal %d %d", sig, *myself->getsigtodo (sig)); switch (sig) { case __SIGFLUSH: @@ -1170,23 +1179,26 @@ wait_sig (VOID *self) /* A normal UNIX signal */ default: sigproc_printf ("Got signal %d", sig); - sig_handle (sig, rc != 2); - /* Need to decrement again to offset increment below since - we really do want to decrement in this case. */ - InterlockedDecrement (myself->getsigtodo (sig)); - goto nextsig; /* FIXME: shouldn't this allow the loop to continue? */ + int res = sig_handle (sig, rc != 2); + if (res > 0) /* Success with handler. Decrement done. */ + continue; + else if (res == 0) /* Cannot launch handler */ + { + /* Signal sigcatch_nosync to insure that we loop */ + ReleaseSemaphore (sigcatch_nosync, 1, NULL); + saw_failed_interrupt = true; + goto quit_loop; + } + /* else SIG_IGN, SIG_DFL, ... */ } + InterlockedDecrement (myself->getsigtodo (sig)); } - - nextsig: - /* Decremented too far. */ - if (InterlockedIncrement (myself->getsigtodo (sig)) > 0) - saw_pending_signals = 1; } if (pending_signals < 0 && !saw_pending_signals) pending_signals = 0; + quit_loop: if (saw_sigchld) proc_subproc (PROC_CLEARWAIT, 0);