Index: trunk/src/emx/src/lib/sys/b_processWait.c
===================================================================
--- trunk/src/emx/src/lib/sys/b_processWait.c	(revision 2210)
+++ trunk/src/emx/src/lib/sys/b_processWait.c	(revision 2211)
@@ -50,4 +50,5 @@
 #include <InnoTekLIBC/backend.h>
 #include <InnoTekLIBC/FastInfoBlocks.h>
+#include <InnoTekLIBC/fork.h>
 #define __LIBC_LOG_GROUP __LIBC_LOG_GRP_BACK_PROCESS
 #include <InnoTekLIBC/logstrict.h>
@@ -119,4 +120,6 @@
 /** List of known children. */
 static volatile PWAITCHILD  gpChildrenHead;
+/** List of free known children. */
+static volatile PWAITCHILD  gpChildrenFree;
 /** Number of known child processes. */
 static volatile unsigned    gcChildren;
@@ -149,4 +152,5 @@
 static int  waitAllocInsert(const PWAITINFO pWaitInsert);
 static inline void waitInfoToSigInfo(const PWAITINFO pWait, siginfo_t *pSigInfo);
+static int processWaitForkChildHook(__LIBC_PFORKHANDLE pForkHandle, __LIBC_FORKOP enmOperation);
 
 
@@ -192,5 +196,5 @@
     if (gtidThread)
     {
-        /* kill the thread */
+        /* kill the thread - this is probably a waste of time in the exitlist handler... */
         __atomic_xchg(&gfTerminate, 1);
         DosKillThread(gtidThread);
@@ -214,4 +218,41 @@
         DosPostEventSem(hev);
         DosCloseEventSem(hev);
+    }
+
+    /*
+     * Kill all known decendants.
+     */
+    PWAITCHILD pChild = gpChildrenHead;
+    if (pChild)
+    {
+        /*
+         * Kill the process tree so we don't end up having childrens
+         * children popping in behind us.
+         *
+         * We boots our priority trying to make sure we get the message
+         * down fast. Going back to regular shouldn't be problem since we're
+         * doing exit lists now anyways.
+         */
+        DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 1, 0);
+        for (; pChild; pChild = pChild->pNext)
+            DosKillProcess(DKP_PROCESSTREE, pChild->pid);
+        DosSetPriority(PRTYS_THREAD, PRTYC_REGULAR, 0, 0);
+        DosSleep(0);
+
+        /*
+         * We reap all possible decendants to as much as possible prevent anyone
+         * waitin for immediate children to not be bothered with it but just get
+         * the heck out and terminate.
+         */
+        RESULTCODES res;
+        PID pid;
+        while (!DosWaitChild(DCWA_PROCESSTREE, DCWW_NOWAIT, &res, &pid, 0))
+            /* nothing */;
+        DosSleep(1); /* penalty / chance to exit */
+        while (!DosWaitChild(DCWA_PROCESSTREE, DCWW_NOWAIT, &res, &pid, 0))
+            /* nothing */;
+        DosSleep(0);
+        while (!DosWaitChild(DCWA_PROCESSTREE, DCWW_NOWAIT, &res, &pid, 0))
+            /* nothing */;
     }
 }
@@ -328,4 +369,6 @@
                     else
                         gpChildrenHead = pChild->pNext;
+                    pChild->pNext = gpChildrenFree;
+                    gpChildrenFree = pChild;
                     __atomic_decrement_min(&gcChildren, 0);
                     break;
@@ -570,6 +613,22 @@
 void __libc_back_processWaitNotifyExec(pid_t pid)
 {
-    PWAITCHILD pChild = _hmalloc(sizeof(*pChild));
-    waitSemRequest(0);
+    /*
+     * Allocate and enter semaphore protection.
+     */
+    PWAITCHILD pChild = NULL;
+    if (gpChildrenFree)
+    {
+        waitSemRequest(0);
+        pChild = gpChildrenFree;
+        if (pChild)
+            gpChildrenFree = pChild->pNext;
+        else
+            waitSemRelease();
+    }
+    if (!pChild)
+    {
+        pChild = _hmalloc(sizeof(*pChild));
+        waitSemRequest(0);
+    }
 
     /*
@@ -979,2 +1038,58 @@
                        rc, pSigInfo->si_pid, pSigInfo->si_code, pSigInfo->si_status);
 }
+
+
+_FORK_CHILD1(0xf0010000, processWaitForkChildHook)
+
+/**
+ * Callback function for registration using _FORK_PARENT1()
+ * or _FORK_CHILD1().
+ *
+ * @returns 0 on success.
+ * @returns positive errno on warning.
+ * @returns negative errno on failure. Fork will be aborted.
+ * @param   pForkHandle     Pointer to fork handle.
+ * @param   enmOperation    Callback operation.
+ */
+static int processWaitForkChildHook(__LIBC_PFORKHANDLE pForkHandle, __LIBC_FORKOP enmOperation)
+{
+    switch (enmOperation)
+    {
+	/*
+	 * Have to reset the globals to indicate no waiter thread.
+	 */
+	case __LIBC_FORK_OP_FORK_CHILD:
+	{
+            PWAITINFO pInfo = gpWaitHead;
+            while (pInfo)
+            {
+                PWAITINFO p = pInfo;
+                pInfo = pInfo->pNext;
+                p->pNext = gpWaitFree;
+                gpWaitFree = pInfo;
+            }
+            gpWaitHead      = NULL;
+            gpWaitTail      = NULL;
+
+            PWAITCHILD pChild = gpChildrenHead;
+            if (pChild)
+            {
+                gpChildrenHead = NULL;
+                pChild->pNext = gpChildrenFree;
+                gpChildrenFree = pChild;
+            }
+            gcChildren      = 0;
+            gcBirths        = 0;
+            gcDeaths        = 0;
+            //gfNoWaitStatus ???
+            gtidThread      = 0;
+            gfTerminate     = 0;
+            break;
+	}
+
+	default:
+	    break;
+    }
+    return 0;
+}
+
