aboutsummaryrefslogtreecommitdiff
path: root/winsup/cygwin/sigproc.cc
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/sigproc.cc')
-rw-r--r--winsup/cygwin/sigproc.cc79
1 files changed, 38 insertions, 41 deletions
diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc
index f924a4c..5efd067 100644
--- a/winsup/cygwin/sigproc.cc
+++ b/winsup/cygwin/sigproc.cc
@@ -85,8 +85,6 @@ Static HANDLE hwait_subproc = NULL; // Handle of sig_subproc thread
Static HANDLE wait_sig_inited = NULL; // Control synchronization of
// message queue startup
-Static muto *sync_proc_subproc = NULL; // Control access to
- // subproc stuff
/* Used by WaitForMultipleObjects. These are handles to child processes.
*/
@@ -100,6 +98,9 @@ Static int nzombies = 0; // Number of deceased children
Static waitq waitq_head = {0, 0, 0, 0, 0, 0, 0};// Start of queue for wait'ing threads
Static waitq waitq_main; // Storage for main thread
+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
@@ -244,7 +245,7 @@ proc_subproc (DWORD what, DWORD val)
int potential_match;
DWORD exitcode;
pinfo *child;
- int send_sigchld = 0;
+ int clearing = 0;
waitq *w;
#define wval ((waitq *) val)
@@ -284,14 +285,6 @@ proc_subproc (DWORD what, DWORD val)
wake_wait_subproc ();
break;
- /* A child is in the stopped state. Scan wait() queue to see if anyone
- * should be notified. (Called from wait_sig thread)
- */
- case PROC_CHILDSTOPPED:
- child = myself; // Just to avoid accidental NULL dereference
- sip_printf ("Received stopped notification");
- goto scan_wait;
-
/* A child process had terminated.
* Possibly this is just due to an exec(). Cygwin implements an exec()
* as a "handoff" from one windows process to another. If child->hProcess
@@ -310,7 +303,6 @@ proc_subproc (DWORD what, DWORD val)
ForceCloseHandle1 (hchildren[val], childhProc);
hchildren[val] = child->hProcess; /* Filled out by child */
ProtectHandle1 (child->hProcess, childhProc);
- wake_wait_subproc ();
break; // This was an exec()
}
@@ -318,14 +310,32 @@ proc_subproc (DWORD what, DWORD val)
child->pid, val, hchildren[val], nchildren, nzombies);
remove_child (val); // Remove from children arrays
zombies[nzombies++] = child; // Add to zombie array
- wake_wait_subproc (); // Notify wait_subproc thread that
- // nchildren has changed.
child->process_state = PID_ZOMBIE;// Walking dead
if (!proc_loop_wait) // Don't bother if wait_subproc is
break; // exiting
- send_sigchld = 1;
+ /* 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.
+
+ /* A child is in the stopped state. Scan wait() queue to see if anyone
+ * should be notified. (Called from wait_sig thread)
+ */
+ case PROC_CHILDSTOPPED:
+ child = myself; // Just to avoid accidental NULL dereference
+ sip_printf ("Received stopped notification");
+ goto scan_wait;
+ /* Clear all waiting threads. Called from exceptions.cc prior to
+ * the main thread's dispatch to a signal handler function.
+ * (called from wait_sig thread)
+ */
+ case PROC_CLEARWAIT:
+ /* Clear all "wait"ing threads. */
+ sip_printf ("clear waiting threads");
+ clearing = 1;
+
+ case PROC_SIGCHLD:
scan_wait:
/* Scan the linked list of wait()ing threads. If a wait's parameters
* match this pid, then activate it.
@@ -334,13 +344,15 @@ proc_subproc (DWORD what, DWORD val)
{
if ((potential_match = checkstate (w)) > 0)
sip_printf ("released waiting thread");
- else if (potential_match < 0)
+ else if (!clearing && potential_match < 0)
sip_printf ("only found non-terminated children");
- else if (potential_match == 0) // nothing matched
+ else if (potential_match <= 0) // nothing matched
{
sip_printf ("waiting thread found no children");
HANDLE oldw = w->next->ev;
w->next->ev = NULL;
+ if (clearing)
+ w->next->status = -1; /* flag that a signal was received */
if (!SetEvent (oldw))
system_printf ("couldn't wake up wait event %p, %E", oldw);
w->next = w->next->next;
@@ -349,32 +361,13 @@ proc_subproc (DWORD what, DWORD val)
break;
}
- sip_printf ("finished processing terminated/stopped child");
- if (!send_sigchld)
- break; // No need to send a SIGCHLD
-
- /* Send a SIGCHLD to myself. */
- sync_proc_subproc->release (); // Avoid a potential deadlock
- rc = sig_send (NULL, SIGCHLD); // Send a SIGCHLD
- goto out1; // Don't try to unlock. We don't have a lock.
-
-
- /* Clear all waiting threads. Called from exceptions.cc prior to
- * the main thread's dispatch to a signal handler function.
- * (called from wait_sig thread)
- */
- case PROC_CLEARWAIT:
- /* Clear all "wait"ing threads. */
- sip_printf ("clear waiting threads");
- for (w = &waitq_head; w->next != NULL; w = w->next)
+ if (!clearing)
+ sip_printf ("finished processing terminated/stopped child");
+ else
{
- sip_printf ("clearing waiting thread, pid %d", w->next->pid);
- w->next->status = -1; /* flag that a signal was received */
- if (!SetEvent (w->next->ev))
- system_printf ("Couldn't wake up wait event, %E");
+ waitq_head.next = NULL;
+ sip_printf ("finished clearing");
}
- waitq_head.next = NULL;
- sip_printf ("finished clearing");
break;
/* Handle a wait4() operation. Allocates an event for the calling
@@ -1252,6 +1245,10 @@ wait_sig (VOID *)
/* A normal UNIX signal */
default:
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);
goto nextsig;
}