Index: /branches/libc-0.6/src/emx/ChangeLog.LIBC
===================================================================
--- /branches/libc-0.6/src/emx/ChangeLog.LIBC	(revision 2795)
+++ /branches/libc-0.6/src/emx/ChangeLog.LIBC	(revision 2796)
@@ -5,4 +5,5 @@
 2006-08-27: knut st. osmundsen <bird-gccos2-spam@anduin.net>
     - libc:
+        o Fixed log problem in fork() child. Fixes #119.
         o Corrected DosSetFHState mask. Fixes #118.
         o Implemented the new length modifiers for *scanf. Adjusted the length
Index: /branches/libc-0.6/src/emx/src/lib/sys/logstrict.c
===================================================================
--- /branches/libc-0.6/src/emx/src/lib/sys/logstrict.c	(revision 2795)
+++ /branches/libc-0.6/src/emx/src/lib/sys/logstrict.c	(revision 2796)
@@ -62,4 +62,5 @@
 #include <machine/param.h>
 #include <InnoTekLIBC/thread.h>
+#include <InnoTekLIBC/fork.h>
 
 #define INCL_BASE
@@ -98,7 +99,9 @@
 *******************************************************************************/
 /** Hex digits. */
-static const char gszHexDigits[17] = "0123456789abcdef";
+static const char       gszHexDigits[17] = "0123456789abcdef";
 /** Uppercase hex digits. */
-static const char gszHexDigitsUpper[17] = "0123456789ABCDEF";
+static const char       gszHexDigitsUpper[17] = "0123456789ABCDEF";
+/** Pointer to default logger instance. */
+static __LIBC_PLOGINST  gpDefault;
 
 
@@ -116,4 +119,5 @@
 static int      __libc_logVSNPrintf(char *pszBuffer, size_t cchBuffer, const char *pszFormat, va_list args);
 static int      __libc_logSNPrintf(char *pszBuffer, size_t cchBuffer, const char *pszFormat, ...) __printflike(3, 4);
+int __libc_logForkParent(__LIBC_PFORKHANDLE pForkHandle, __LIBC_FORKOP enmOperation);
 
 
@@ -247,4 +251,12 @@
             while (i-- > 0)
                 DosClose(ah[i]);
+
+            ULONG fulFlags = ~0U;
+            if (DosQueryFHState(pInst->hFile, &fulFlags) == NO_ERROR)
+            {
+                fulFlags |= OPEN_FLAGS_NOINHERIT;
+                fulFlags &= OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_NO_CACHE | OPEN_FLAGS_NOINHERIT; /* Turn off non-participating bits. */
+                DosSetFHState(pInst->hFile, fulFlags);
+            }
         }
     }
@@ -263,19 +275,21 @@
         int         cch;
 
+        /* The current time+date and basic process attributes. */
         DosGetInfoBlocks(&pTib, &pPib);
         DosGetDateTime(&dt);
-
         cch = __libc_logSNPrintf(pszMsg, CCHTMPMSGBUFFER,
                                  "Opened log at %04d-%02d-%02d %02d:%02d:%02d.%02d\n"
-                                 "Process ID: %#x (%d) Parent PID: %#x (%d)\n",
+                                 "Process ID: %#x (%d) Parent PID: %#x (%d) Type: %d\n",
                                  dt.year, dt.month, dt.day, dt.hours, dt.minutes, dt.seconds, dt.hundredths,
-                                 (int)pPib->pib_ulpid, (unsigned)pPib->pib_ulpid, (int)pPib->pib_ulppid, (unsigned)pPib->pib_ulppid);
+                                 (int)pPib->pib_ulpid, (unsigned)pPib->pib_ulpid, (int)pPib->pib_ulppid, (unsigned)pPib->pib_ulppid,
+                                 (int)pPib->pib_ultype);
         DosWrite(pInst->hFile, pszMsg, cch, &cb);
 
+        /* The executable module. */
         cch = __libc_logSNPrintf(pszMsg, CCHTMPMSGBUFFER,
                                  "Exe hmte  : %#x (",
                                  (unsigned)pPib->pib_hmte);
         DosWrite(pInst->hFile, pszMsg, cch, &cb);
-        if (DosQueryModuleName(pPib->pib_hmte, CCHTMPMSGBUFFER, pszMsg))
+        if (DosQueryModuleName(pPib->pib_hmte, CCHTMPMSGBUFFER - 4, pszMsg))
             pszMsg[0] = '\0';
         cch = strlen(pszMsg);
@@ -284,4 +298,5 @@
         DosWrite(pInst->hFile, pszMsg, cch, &cb);
 
+        /* The raw arguments. */
         cch = __libc_logSNPrintf(pszMsg, CCHTMPMSGBUFFER,
                                  "First arg : %s\n"
@@ -292,19 +307,53 @@
         cch = strlen(psz);
         DosWrite(pInst->hFile, psz, cch, &cb);
-
-        char    szMod[CCHMAXPATH];
+        DosWrite(pInst->hFile, "\n", 1, &cb);
+
+        /* The current drive and directory. */
+        ULONG ulDisk = 0;
+        ULONG fLogical = 0;
+        if (!DosQueryCurrentDisk(&ulDisk, &fLogical))
+        {
+            cch = __libc_logSNPrintf(pszMsg, CCHTMPMSGBUFFER,
+                                     "Cur dir   : %c:\\",
+                                     (char)ulDisk + ('A' - 1));
+            DosWrite(pInst->hFile, pszMsg, cch, &cb);
+
+            ULONG cchDir = CCHTMPMSGBUFFER - 4;
+            if (DosQueryCurrentDir(ulDisk, (PSZ)pszMsg, &cchDir))
+                pszMsg[0] = '\0';
+            cch = strlen(pszMsg);
+            pszMsg[cch++] = '\n';
+            DosWrite(pInst->hFile, pszMsg, cch, &cb);
+        }
+
+        /* The CRT module. */
+        char    szMod[128];
         ULONG   iObj = ~0;
         ULONG   offObj = ~0;
         HMODULE hmod = ~0;
         if (DosQueryModFromEIP(&hmod, &iObj, sizeof(szMod), &szMod[0], &offObj, (uintptr_t)__libc_logInit))
+        {
             szMod[0] = '\0';
+            hmod = NULLHANDLE;
+        }
         cch = __libc_logSNPrintf(pszMsg, CCHTMPMSGBUFFER,
-                                 "\n"
-                                 "CRT Module: %s hmod=%#lx\n"
+                                 "CRT Module: %s hmod=%#lx (",
+                                 szMod, hmod);
+        DosWrite(pInst->hFile, pszMsg, cch, &cb);
+
+        if (    hmod == NULLHANDLE
+            ||  DosQueryModuleName(hmod, CCHTMPMSGBUFFER - 4, pszMsg))
+            pszMsg[0] = '\0';
+        cch = strlen(pszMsg);
+        pszMsg[cch++] = ')';
+        pszMsg[cch++] = '\n';
+        DosWrite(pInst->hFile, pszMsg, cch, &cb);
+
+        cch = __libc_logSNPrintf(pszMsg, CCHTMPMSGBUFFER,
                                  "__libc_logInit: addr %p iObj=%ld offObj=%#lx\n",
-                                 szMod, hmod, (void *)__libc_logInit, iObj, offObj);
+                                 (void *)__libc_logInit, iObj, offObj);
         DosWrite(pInst->hFile, pszMsg, cch, &cb);
 
-
+        /* column headers */
         cch = __libc_logSNPrintf(pszMsg, CCHTMPMSGBUFFER,
                                  "   Millsecond Timestamp.\n"
@@ -436,11 +485,9 @@
 static void *__libc_logDefault(void)
 {
-    /** Pointer to default logger instance. */
-    static __LIBC_PLOGINST  pDefault;
     /** Set if we've already tried to init the log, but failed. */
     static int              fAlreadyTried;
 
-    if (pDefault)
-        return pDefault;
+    if (gpDefault)
+        return gpDefault;
     else if (!fAlreadyTried)
     {
@@ -501,5 +548,5 @@
         __libc_logSNPrintf(szFilename, sizeof(szFilename), "libc_%04x.log", getPid());
         if (__libc_logInit(&DefInst, 0, &DefGrps, szFilename))
-            pDefault = &DefInst;
+            gpDefault = &DefInst;
 
         /*
@@ -509,5 +556,5 @@
     }
 
-    return pDefault;
+    return gpDefault;
 }
 
@@ -2210,2 +2257,163 @@
 }
 
+
+/**
+ * Procedure invoked by the parent for aligning the log file handle
+ * and semaphore handle with the parent ones.
+ *
+ * @returns 0 on success.
+ * @returns -errno on failure.
+ * @param pForkHandle   The fork handle
+ * @param pvArg         Pointer to a __LIBC_LOGINST containing the parent handles.
+ * @param cbArg         sizeof(__LIBC_LOGINST).
+ */
+static int __libc_logForkChildRelocate(__LIBC_PFORKHANDLE pForkHandle, void *pvArg, size_t cbArg)
+{
+    const __LIBC_LOGINST *pParent = (const __LIBC_LOGINST *)pvArg;
+
+    /*
+     * Make sure there is a log handle.
+     */
+    __LIBC_PLOGINST pChild = gpDefault;
+    if (!pChild)
+    {
+        pChild = __libc_logDefault();
+        if (!pChild)
+            return 0;
+    }
+
+    /*
+     * The file handle.
+     */
+    if (    pParent->hFile != pChild->hFile
+        &&  pParent->hFile >= 0
+        &&  pChild->hFile  >= 0)
+    {
+        HFILE hNew = pParent->hFile;
+        APIRET rc = DosDupHandle(pChild->hFile, &hNew);
+        if (rc == ERROR_TOO_MANY_OPEN_FILES)
+        {
+            DosSetMaxFH(pParent->hFile + 1);
+            hNew = pParent->hFile;
+            rc = DosDupHandle(pChild->hFile, &hNew);
+        }
+        if (rc == NO_ERROR)
+        {
+            /* mark it non-inherit */
+            ULONG fulFlags = ~0U;
+            rc = DosQueryFHState(hNew, &fulFlags);
+            if (rc == NO_ERROR)
+            {
+                fulFlags |= OPEN_FLAGS_NOINHERIT;
+                fulFlags &= OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_NO_CACHE | OPEN_FLAGS_NOINHERIT; /* Turn off non-participating bits. */
+                rc = DosSetFHState(hNew, fulFlags);
+            }
+            if (rc == NO_ERROR)
+                __libc_LogMsg(0, pChild, 0xffff, __FUNCTION__,
+                              "Successfully relocated the log handle from %ld to %ld\n", pChild->hFile, hNew);
+            else
+                __libc_LogError(0, pChild, 0xffff, __FUNCTION__, __FILE__, __LINE__,
+                                "Failed to modify the inherit flag of %ld. rc=%ld. fulFlags=%lx\n", hNew, rc, fulFlags);
+
+            /* replace. */
+            DosClose(pChild->hFile);
+            pChild->hFile = hNew;
+
+        }
+        else
+            __libc_LogError(0, pChild, 0xffff, __FUNCTION__, __FILE__, __LINE__,
+                            "DosDupHandle(%ld, %ld) -> %ld\n", pChild->hFile, pParent->hFile, rc);
+    }
+
+    /*
+     * The mutex handle.
+     */
+    if (    pParent->hmtx != pChild->hmtx
+        &&  pParent->hmtx != NULLHANDLE
+        &&  pChild->hmtx  != NULLHANDLE)
+    {
+        APIRET rc = NO_ERROR;
+        if ((pParent->hmtx & 0xffff) < 0x3000) /* I'm so sorry, but if it's higher than 0x3000 we can't run the risk of exhausting the stack. */
+        {
+            /*
+             * Mutex handles are allocated in ascending order, so we'll have to allocate
+             * mutexes until we get or pass the desired handle.
+             */
+            struct __LIBC_LOGFORKMTXRELOC
+            {
+                struct __LIBC_LOGFORKMTXRELOC *pNext;
+                int         iCur;
+                HMTX        ahmtx[128];
+            }  *pHead = NULL,
+               *pNew;
+            for (;;)
+            {
+                HMTX hmtx;
+                rc = DosCreateMutexSem(NULL, &hmtx, 0, FALSE);
+                if (rc != NO_ERROR)
+                    break;
+                if (hmtx == pParent->hmtx)
+                {
+                    __libc_LogMsg(0, pChild, 0xffff, __FUNCTION__,
+                                  "Successfully relocated the log mutex from %ld to %ld\n", pChild->hmtx, hmtx);
+                    DosCloseMutexSem(pChild->hmtx);
+                    pChild->hmtx = hmtx;
+                    break;
+                }
+                if (hmtx > pParent->hmtx)
+                    break;
+
+                /* record it */
+                if (    pHead == NULL
+                    ||  pHead->iCur >= sizeof(pNew->ahmtx) / sizeof(pNew->ahmtx[0]))
+                {
+                    pNew = alloca(sizeof(*pNew));
+                    if (!pNew)
+                    {
+                        DosCloseMutexSem(hmtx);
+                        break;
+                    }
+                    pNew->iCur = 0;
+                    pNew->pNext = pHead;
+                    pHead = pNew;
+                }
+                pHead->ahmtx[pHead->iCur++] = hmtx;
+            }
+
+            /* Cleanup */
+            while (pHead)
+            {
+                while (pHead->iCur-- > 0)
+                    DosCloseMutexSem(pHead->ahmtx[pHead->iCur]);
+                pHead = pHead->pNext;
+            }
+        }
+        if (pChild->hmtx != pParent->hmtx)
+            __libc_LogError(0, pChild, 0xffff, __FUNCTION__, __FILE__, __LINE__,
+                            "Failed to relocate the mutex.  parent=%#lx child=%#lx rc=%ld\n", pParent->hmtx, pChild->hmtx, rc);
+    }
+
+    /* We don't fail the fork() even if the log relocation fails. */
+    return 0;
+}
+
+
+/**
+ * Fork callback which will make sure the child log handles are reallocated
+ * so they are identical to the ones used in the parent.
+ *
+ * @returns 0 on success.
+ * @returns -errno on failure.
+ * @param   pForkHandle     Pointer to fork handle.
+ * @param   enmOperation    Fork operation.
+ */
+int __libc_logForkParent(__LIBC_PFORKHANDLE pForkHandle, __LIBC_FORKOP enmOperation)
+{
+    if (    enmOperation == __LIBC_FORK_OP_EXEC_PARENT
+        &&  gpDefault)
+        return pForkHandle->pfnInvoke(pForkHandle, __libc_logForkChildRelocate, gpDefault, sizeof(*gpDefault));
+    return 0;
+}
+
+_FORK_PARENT1(0xfffffff0, __libc_logForkParent)
+
