diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 03e7ccccc..bfa930b21 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,6 +1,17 @@ -Wed Feb 23 22:51:27 2000 Christopher Faylor +Thu Feb 24 00:59:15 2000 Christopher Faylor Fix final round of gcc warnings relating to unused parameters. + * debug.cc (iscygthread): New function. + * debug.h: Declare it. + * exceptions.cc (set_process_mask): Flush pending signals. + (handle_sigsuspend): No need to flush pending signals. + (call_handler): Refine previous tests of muto ownership. Only clear + wait()'s when we have definitely responded to a signal. + * fhandler_console.cc (fhandler_console::read): Don't set EINTR if + executing in a "cygwin" thread. + * sigproc.cc (proc_subproc): Use second argument to control whether + CLEARWAIT actually sets "signalled" flag. + * sync.h (muto): Add 'unstable' method. Wed Feb 23 21:59:44 2000 Christopher Faylor @@ -10,7 +21,7 @@ Wed Feb 23 21:34:58 2000 Christopher Faylor * exceptions.cc (interruptible): Change method for determining if something is interruptible. - (call_handler): Avoid suspending a thread if it owns a mutex. Only set + (call_handler): Avoid suspending a thread if it owns a muto. Only set signal_arrived if the thread was actually interrupted. (events_init): Initialize module information needed by interruptible(). (sigdelayed): Don't call sig_dispatch_pending since it could screw up @@ -20,8 +31,6 @@ Wed Feb 23 21:34:58 2000 Christopher Faylor bulk of the processing comes from the signal thread. (wait_sig): Force processing of waiting threads if SIGCHLD is not processed. - * sync.cc (muto::release): Set tid == 0 after lock is released or - signal processor will be confused. Tue Feb 22 23:06:01 2000 Christopher Faylor diff --git a/winsup/cygwin/debug.cc b/winsup/cygwin/debug.cc index 077ccf088..6218312fe 100644 --- a/winsup/cygwin/debug.cc +++ b/winsup/cygwin/debug.cc @@ -47,6 +47,17 @@ regthread (const char *name, DWORD tid) unlock_threadname (); } +int __stdcall +iscygthread() +{ + DWORD tid = GetCurrentThreadId (); + if (tid != maintid) + for (DWORD i = 0; i < NTHREADS && threads[i].name != NULL; i++) + if (threads[i].id == tid) + return 1; + return 0; +} + struct thread_start { LONG notavail; diff --git a/winsup/cygwin/debug.h b/winsup/cygwin/debug.h index c8e28ba64..d57ea4d0e 100644 --- a/winsup/cygwin/debug.h +++ b/winsup/cygwin/debug.h @@ -30,6 +30,7 @@ void threadname_init (); HANDLE __stdcall makethread (LPTHREAD_START_ROUTINE, LPVOID, DWORD, const char *); const char * __stdcall threadname (DWORD, int lockit = TRUE); void __stdcall regthread (const char *, DWORD); +int __stdcall iscygthread (); #ifndef DEBUGGING # define ForceCloseHandle CloseHandle diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index 4f2aa15c3..4176f66cc 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -598,7 +598,6 @@ handle_sigsuspend (sigset_t tempmask) // interested in through. sigproc_printf ("old mask %x, new mask %x", oldmask, tempmask); - sig_dispatch_pending (0); WaitForSingleObject (signal_arrived, INFINITE); set_sig_errno (EINTR); // Per POSIX @@ -705,6 +704,7 @@ set_sig_errno (int e) { set_errno (e); sigsave.saved_errno = e; + debug_printf ("errno %d", e); } static int @@ -738,21 +738,21 @@ call_handler (int sig, struct sigaction& siga, void *handler) for (;;) { res = SuspendThread (hth); - /* FIXME: Make multi-thread aware */ - if (sync_proc_subproc->owner () != maintid && mask_sync->owner () != maintid) - break; if (res) goto set_pending; + + /* FIXME: Make multi-thread aware */ + if (!sync_proc_subproc->unstable () && sync_proc_subproc->owner () != maintid && + !mask_sync->unstable () && mask_sync->owner () != maintid) + break; + ResumeThread (hth); Sleep (0); } sigproc_printf ("suspend said %d, %E", res); - /* Clear any waiting threads prior to dispatching to handler function */ - proc_subproc(PROC_CLEARWAIT, 0); - if (sigsave.cx) { cx = sigsave.cx; @@ -782,8 +782,15 @@ call_handler (int sig, struct sigaction& siga, void *handler) } (void) ResumeThread (hth); + if (interrupted) - (void) SetEvent (signal_arrived); // For an EINTR case + { + /* Clear any waiting threads prior to dispatching to handler function */ + proc_subproc(PROC_CLEARWAIT, 1); + /* Apparently we have to set signal_arrived after resuming the thread or it + is possible that the event will be ignored. */ + (void) SetEvent (signal_arrived); // For an EINTR case + } sigproc_printf ("armed signal_arrived %p, res %d", signal_arrived, res); out: @@ -840,11 +847,16 @@ ctrl_c_handler (DWORD type) extern "C" void __stdcall set_process_mask (sigset_t newmask) { + extern DWORD sigtid; + mask_sync->acquire (INFINITE); + sigset_t oldmask = myself->getsigmask (); newmask &= ~SIG_NONMASKABLE; 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) + sig_dispatch_pending (); return; } @@ -1076,7 +1088,7 @@ _sigreturn: addl $4,%%esp call _set_process_mask@4 popl %%eax # saved errno - testl %%eax,%%eax # lt 0 + testl %%eax,%%eax # Is it < 0 jl 1f # yup. ignore it movl %1,%%ebx movl %%eax,(%%ebx) diff --git a/winsup/cygwin/fhandler_console.cc b/winsup/cygwin/fhandler_console.cc index 40e2954ee..67732ba1c 100644 --- a/winsup/cygwin/fhandler_console.cc +++ b/winsup/cygwin/fhandler_console.cc @@ -151,7 +151,8 @@ fhandler_console::read (void *pv, size_t buflen) case WAIT_OBJECT_0: break; case WAIT_OBJECT_0 + 1: - set_sig_errno (EINTR); + if (!iscygthread ()) + set_sig_errno (EINTR); return -1; default: __seterrno (); diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index 5efd067d6..7c1f449ed 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -102,7 +102,7 @@ muto NO_COPY *sync_proc_subproc = NULL; // Control access to // subproc stuff DWORD NO_COPY maintid = 0; // ID of the main thread -Static DWORD sigtid = 0; // ID of the signal thread +DWORD NO_COPY sigtid = 0; // ID of the signal thread int NO_COPY pending_signals = 0; // TRUE if signals pending @@ -245,7 +245,7 @@ proc_subproc (DWORD what, DWORD val) int potential_match; DWORD exitcode; pinfo *child; - int clearing = 0; + int clearing; waitq *w; #define wval ((waitq *) val) @@ -316,7 +316,7 @@ proc_subproc (DWORD what, DWORD val) /* Send a SIGCHLD to myself. */ rc = sig_send (myself_nowait, SIGCHLD); // Send a SIGCHLD - break; // Don't try to unlock. We don't have a lock. + break; /* A child is in the stopped state. Scan wait() queue to see if anyone * should be notified. (Called from wait_sig thread) @@ -324,6 +324,7 @@ proc_subproc (DWORD what, DWORD val) case PROC_CHILDSTOPPED: child = myself; // Just to avoid accidental NULL dereference sip_printf ("Received stopped notification"); + clearing = 0; goto scan_wait; /* Clear all waiting threads. Called from exceptions.cc prior to @@ -333,9 +334,8 @@ proc_subproc (DWORD what, DWORD val) case PROC_CLEARWAIT: /* Clear all "wait"ing threads. */ sip_printf ("clear waiting threads"); - clearing = 1; + clearing = val; - case PROC_SIGCHLD: scan_wait: /* Scan the linked list of wait()ing threads. If a wait's parameters * match this pid, then activate it. @@ -476,7 +476,7 @@ proc_terminate (void) ForceCloseHandle1 (h, hwait_subproc); sync_proc_subproc->acquire(WPSP); - (void) proc_subproc (PROC_CLEARWAIT, 0); + (void) proc_subproc (PROC_CLEARWAIT, 1); lock_pinfo_for_update (INFINITE); /* Clean out zombie processes from the pid list. */ @@ -1205,6 +1205,8 @@ wait_sig (VOID *) * array looking for any unprocessed signals. */ pending_signals = 0; + int saw_sigchld = 0; + int dispatched_sigchld = 0; for (int sig = -__SIGOFFSET; sig < NSIG; sig++) { #ifdef NOSIGQUEUE @@ -1213,6 +1215,8 @@ wait_sig (VOID *) while (InterlockedDecrement (myself->getsigtodo(sig)) >= 0) #endif { + if (sig == SIGCHLD) + saw_sigchld = 1; if (sig > 0 && sig != SIGCONT && sig != SIGKILL && sig != SIGSTOP && (sigismember (& myself->getsigmask (), sig) || myself->process_state & PID_STOPPED)) @@ -1247,9 +1251,8 @@ wait_sig (VOID *) sip_printf ("Got signal %d", sig); int wasdispatched = sig_handle (sig); dispatched |= wasdispatched; - if (sig == SIGCHLD && !wasdispatched) - proc_subproc (PROC_SIGCHLD, 0); - dispatched |= sig_handle (sig); + if (sig == SIGCHLD && wasdispatched) + dispatched_sigchld = 1; goto nextsig; } } @@ -1262,6 +1265,8 @@ wait_sig (VOID *) continue; } + if (saw_sigchld && !dispatched_sigchld) + proc_subproc (PROC_CLEARWAIT, 0); /* Signal completion of signal handling depending on which semaphore * woke up the WaitForMultipleObjects above. */ diff --git a/winsup/cygwin/sigproc.h b/winsup/cygwin/sigproc.h index 7f237a925..b1b4eafc0 100644 --- a/winsup/cygwin/sigproc.h +++ b/winsup/cygwin/sigproc.h @@ -18,8 +18,7 @@ enum procstuff PROC_CHILDSTOPPED = 2, // a child stopped PROC_CHILDTERMINATED = 3, // a child died PROC_CLEARWAIT = 4, // clear all waits - signal arrived - PROC_WAIT = 5, // setup for wait() for subproc - PROC_SIGCHLD = 6 // saw a non-trapped SIGCHLD + PROC_WAIT = 5 // setup for wait() for subproc }; typedef struct struct_waitq diff --git a/winsup/cygwin/sync.cc b/winsup/cygwin/sync.cc index 96102828b..f9edb9935 100644 --- a/winsup/cygwin/sync.cc +++ b/winsup/cygwin/sync.cc @@ -103,11 +103,11 @@ muto::release () /* FIXME: Need to check that other thread has not exited, too. */ if (!--visits) { + tid = 0; /* We were the last unlocker. */ InterlockedExchange (&sync, 0); /* Reset trigger. */ /* This thread had incremented waiters but had never decremented it. Decrement it now. If it is >= 0 then there are possibly other threads waiting for the lock, so trigger bruteforce. */ - tid = 0; /* We were the last unlocker. */ if (InterlockedDecrement (&waiters) >= 0) (void) SetEvent (bruteforce); /* Wake up one of the waiting threads */ } diff --git a/winsup/cygwin/sync.h b/winsup/cygwin/sync.h index 7189ae936..3dcc915da 100644 --- a/winsup/cygwin/sync.h +++ b/winsup/cygwin/sync.h @@ -37,6 +37,7 @@ public: /* Return true if caller thread owns the lock. */ int ismine () {return tid == GetCurrentThreadId ();} DWORD owner () {return tid;} + int unstable () {return !tid && (sync || waiters >= 0);} }; /* Use a statically allocated buffer as the storage for a muto */