Index: /trunk/libc/include/InnoTekLIBC/sharedpm.h
===================================================================
--- /trunk/libc/include/InnoTekLIBC/sharedpm.h	(revision 2936)
+++ /trunk/libc/include/InnoTekLIBC/sharedpm.h	(revision 2937)
@@ -653,15 +653,4 @@
 
 /**
- * Initializes the shared process management for this process.
- *
- * This might actually initialize the SPM globally too if this is the
- * first process using it.
- *
- * @returns 0 on success.
- * @returns Negative error code (errno.h) on failure.
- */
-int __libc_spmInit(void);
-
-/**
  * Gets the current process.
  *
@@ -669,6 +658,7 @@
  * @returns NULL and errno on failure.
  * @remark  For this too __libc_spmRelease() must be called when done.
- */
-__LIBC_PSPMPROCESS __libc_spmSelf(void);
+ * @param   fAutoInit   Set if it's ok to automatically initialize SPM.
+ */
+__LIBC_PSPMPROCESS __libc_spmSelf(int fAutoInit);
 
 /**
Index: /trunk/libc/src/kNIX/Makefile.kmk
===================================================================
--- /trunk/libc/src/kNIX/Makefile.kmk	(revision 2936)
+++ /trunk/libc/src/kNIX/Makefile.kmk	(revision 2937)
@@ -36,4 +36,5 @@
 libc_kNIX_SOURCES = \
     $(PATH_LIBC_SRC)/kNIX/b_initterm.c \
+    $(PATH_LIBC_SRC)/kNIX/b_initArgv.c \
     $(PATH_LIBC_SRC)/kNIX/b_fhImport.c \
     $(PATH_LIBC_SRC)/kNIX/b_fhValidate.c \
@@ -178,5 +179,6 @@
     $(PATH_LIBC_SRC)/kNIX/os2/_os2_bad.c \
     $(PATH_LIBC_SRC)/kNIX/os2/__spawnve.c \
-    $(PATH_LIBC_SRC)/kNIX/os2/__read_kbd.c
+    $(PATH_LIBC_SRC)/kNIX/os2/__read_kbd.c \
+    $(PATH_LIBC_SRC)/kNIX/os2/__select.c
 TODO= \
     $(PATH_LIBC_SRC)/kNIX/os2/__init.c \
Index: /trunk/libc/src/kNIX/b_initArgv.c
===================================================================
--- /trunk/libc/src/kNIX/b_initArgv.c	(revision 2937)
+++ /trunk/libc/src/kNIX/b_initArgv.c	(revision 2937)
@@ -0,0 +1,183 @@
+/* $Id: $ */
+/** @file
+ *
+ * kNIX - Initialize the argument vector.
+ *
+ * Copyright (c) 1992-1998 by Eberhard Mattes
+ * Copyright (c) 2003-2006 knut st. osmundsen <bird-srcspam@anduin.net>
+ *
+ *
+ * This file is part of kLIBC.
+ *
+ * kLIBC is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * kLIBC is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with kLIBC; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "kNIX.h"
+#define __LIBC_LOG_GROUP __LIBC_LOG_GRP_INITTERM
+#include <klibc/logstrict.h>
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+int __libc_Back_gcArgs;
+char ** __libc_Back_gpapszArgs;
+
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+/** Helper macros for parse_args
+ * @{ */
+#define PUTC(ch) \
+    do { \
+        cbArgs++; \
+        if (pbPool != NULL) \
+            *pbPool++ = (ch); \
+    } while (0)
+#define PUTV \
+    do { \
+        __libc_Back_gcArgs++; \
+        if (papszArgs != NULL) \
+            *papszArgs++ = pbPool; \
+    } while (0)
+#define IS_WHITE(ch)    ((ch) == ' ' || (ch) == '\t')
+/** @} */
+
+
+/**
+ * Parses the argument string passed in as src.
+ *
+ * @returns size of the processed arguments.
+ * @param   pszSrc      Pointer two sequent zero terminated string containing
+ *                      the arguments to be parsed.
+ * @param   pbPool      Pointer to memory pbPool to put the arguments into.
+ *                      NULL allowed.
+ * @param   papszArgs   Pointer to argument vector to put argument pointers in.
+ *                      NULL allowed.
+ */
+static size_t parse_args(const char *pszSrc, char **papszArgs, char *pbPool)
+{
+    size_t cbArgs = 0;
+    __libc_Back_gcArgs = 0;
+
+    /* papszArgs[0] */
+    PUTC((char)_ARG_NONZERO);
+    PUTV;
+    for (;;)
+    {
+        PUTC(*pszSrc);
+        if (*pszSrc == 0)
+            break;
+        ++pszSrc;
+    }
+    ++pszSrc;
+    for (;;)
+    {
+        while (IS_WHITE(*pszSrc))
+            ++pszSrc;
+        if (*pszSrc == 0)
+            break;
+        char *pfFlags = pbPool;
+        PUTC((char)_ARG_NONZERO);
+        PUTV;
+        int cBackspaces = 0;
+        char chQuote = 0;
+        for (;;)
+        {
+            if (!chQuote ? (*pszSrc == '"' || *pszSrc == '\'') : *pszSrc == chQuote)
+            {
+                while (cBackspaces >= 2)
+                {
+                    PUTC('\\');
+                    cBackspaces -= 2;
+                }
+                if (cBackspaces & 1)
+                    PUTC(*pszSrc);
+                else
+                {
+                    chQuote = chQuote ? 0 : *pszSrc;
+                    if (pfFlags != NULL)
+                        *pfFlags |= _ARG_DQUOTE;
+                }
+                cBackspaces = 0;
+            }
+            else if (*pszSrc == '\\')
+                ++cBackspaces;
+            else
+            {
+                while (cBackspaces != 0)
+                {
+                    PUTC('\\');
+                    --cBackspaces;
+                }
+                if (*pszSrc == 0 || (IS_WHITE(*pszSrc) && !chQuote))
+                    break;
+                PUTC(*pszSrc);
+            }
+            ++pszSrc;
+        }
+        PUTC(0);
+    }
+    return cbArgs;
+}
+
+
+/**
+ * Initializes the argument vector.
+ *
+ * @returns 0 on success, non-zero on failure.
+ * @param   pcArgs      Where to store the argument count.
+ * @param   ppapszArgs  Where to store the vector pointer.
+ * @param   fFlags      Init flags.
+ */
+int __libc_Back_initArgv(int *pcArgs, char ***ppapszArgs, unsigned fFlags)
+{
+    LIBCLOG_ENTER("pcArgs=%p ppapszArgs=%p fFlags=%u\n", (void *)pcArgs, (void *)ppapszArgs, fFlags);
+
+    /* Parse the command line to figure the size. */
+    size_t cb = parse_args(fibGetCmdLine(), NULL, NULL);
+    cb += (__libc_Back_gcArgs + 2) * sizeof(char *);
+
+    /* Allocate the pointer array and string buffers and do the command line parsing for real. */
+    __libc_Back_gpapszArgs = (char **)_hmalloc(cb);
+    if (!__libc_Back_gpapszArgs)
+        LIBCLOG_ERROR_RETURN_INT(-ENOMEM);
+    parse_args(fibGetCmdLine(), __libc_Back_gpapszArgs, (char *)&__libc_Back_gpapszArgs[__libc_Back_gcArgs + 2]);
+
+    /* Do responsefiles and wildcards if requested. */
+    if (fFlags & __LIBC_INIT_FLAGS_EXPAND_RESPONSE_FILE)
+        _response(&__libc_Back_gcArgs, &__libc_Back_gpapszArgs);
+    if (fFlags & __LIBC_INIT_FLAGS_EXPAND_WILDCARDS)
+        _wildcard(&__libc_Back_gcArgs, &__libc_Back_gpapszArgs);
+
+    /* output */
+    *pcArgs = __libc_Back_gcArgs;
+    *ppapszArgs = __libc_Back_gpapszArgs;
+
+#ifdef DEBUG_LOGGING
+    /* log it */
+    int iArg;
+    for (iArg = 0; iArg < __libc_Back_gcArgs; iArg++)
+        LIBCLOG_MSG("arg #%d: %s\n", iArg, __libc_Back_gpapszArgs[iArg]);
+#endif
+
+    LIBCLOG_RETURN_INT(0);
+}
+
Index: /trunk/libc/src/kNIX/b_initterm.c
===================================================================
--- /trunk/libc/src/kNIX/b_initterm.c	(revision 2936)
+++ /trunk/libc/src/kNIX/b_initterm.c	(revision 2937)
@@ -134,11 +134,31 @@
      */
     const int32_t cRefs = __atomic_increment_s32(&g_ckNIXUsers);
-    if (cRefs != 1)
-        LIBCLOG_RETURN_MSG(0, "ret 0 (g_ckNIXUsers=%d)\n", cRefs);
-    int rc = __libc_back_init(hmod, pvOS, fFlags);
+    int rc;
+    if (cRefs == 1)
+        rc = __libc_back_init(hmod, pvOS, fFlags);
+    else
+        /* (Might later add initialization code for every module here.) */
+        rc = 0;
     if (!rc)
         LIBCLOG_RETURN_INT(0);
+
+    /* failure */
     __atomic_decrement_s32(&g_ckNIXUsers);
     LIBCLOG_ERROR_RETURN_INT(rc);
 }
 
+
+/**
+ * Terminates the backend.
+ * Called when a frontend shuts down.
+ *
+ * @returns 0 on success, non-zero on failure.
+ * @param   hmod        The handle of the module that's causing the frontend to shut down.
+ * @param   pvOS        OS specific argument.
+ * @param   fFlags      Termination flags.
+ */
+int __libc_Back_term(uintptr_t hmod, void *pvOS, unsigned fFlags)
+{
+    /** @todo */
+    return 0;
+}
Index: /trunk/libc/src/kNIX/os2/b_initterm-os2.c
===================================================================
--- /trunk/libc/src/kNIX/os2/b_initterm-os2.c	(revision 2936)
+++ /trunk/libc/src/kNIX/os2/b_initterm-os2.c	(revision 2937)
@@ -70,56 +70,56 @@
 {
     LIBCLOG_ENTER("hmod=%tx pvOS=%p fFlags=%#x\n", hmod, pvOS, fFlags);
-    int rc = __libc_spmInit();
+    /*
+     * Initialize _osmajor and _osminor.
+     */
+    ULONG aul[2] = {0, 0};
+    DosQuerySysInfo(QSV_VERSION_MAJOR, QSV_VERSION_MINOR, &aul[0], sizeof(aul));
+    _osminor = (unsigned char)aul[1];
+    _osmajor = (unsigned char)aul[0];
+
+    /*
+     * Check for high memory (>512MB) support.
+     */
+    ULONG ul;
+    __libc_back_gcbVirtualAddressLimit = 512 * 1024 * 1024;
+    if (    !DosQuerySysInfo(QSV_VIRTUALADDRESSLIMIT, QSV_VIRTUALADDRESSLIMIT, &ul, sizeof(ul))
+        &&  ul > 512
+        &&  (   (_osmajor == 20 && _osminor >= 40)
+             || _osmajor > 20 /* yeah, sure! */) )
+        __libc_back_gcbVirtualAddressLimit = ul * 1024*1024;
+
+    /*
+     * Initialize TLS.
+     */
+    int rc = DosAllocThreadLocalMemory(1, (PULONG*)(void*)&__libc_gpTLS);
     if (!rc)
     {
-        /*
-         * Initialize _osmajor and _osminor.
-         */
-        ULONG aul[2] = {0, 0};
-        DosQuerySysInfo(QSV_VERSION_MAJOR, QSV_VERSION_MINOR, &aul[0], sizeof(aul));
-        _osminor = (unsigned char)aul[1];
-        _osmajor = (unsigned char)aul[0];
-
-        /*
-         * Check for high memory (>512MB) support.
-         */
-        ULONG ul;
-        __libc_back_gcbVirtualAddressLimit = 512 * 1024 * 1024;
-        if (    !DosQuerySysInfo(QSV_VIRTUALADDRESSLIMIT, QSV_VIRTUALADDRESSLIMIT, &ul, sizeof(ul))
-            &&  ul > 512
-            &&  (   (_osmajor == 20 && _osminor >= 40)
-                 || _osmajor > 20 /* yeah, sure! */) )
-            __libc_back_gcbVirtualAddressLimit = ul * 1024*1024;
-
-        /*
-         * Initialize TLS.
-         */
-        rc = DosAllocThreadLocalMemory(1, (PULONG*)(void*)&__libc_gpTLS);
+        rc = _fmutex_create2(&__libc_gmtxExec,  0, "LIBC SYS Exec Mutex");
         if (!rc)
         {
-            rc = _fmutex_create2(&__libc_gmtxExec,  0, "LIBC SYS Exec Mutex");
-            if (!rc)
+            /* Ensure that SPM is initialized. */
+            __LIBC_PSPMPROCESS pSelf = __libc_spmSelf(1 /* auto init */);
+            if (pSelf)
             {
-                __LIBC_PSPMPROCESS pSelf = __libc_spmSelf();
-                if (!pSelf)
-                {
-                    /*
-                     * Done here.
-                     */
-                    LIBCLOG_RETURN_INT(0);
-                }
-                else
-                {
-                    LIBC_ASSERTM_FAILED("__libc_spmSelf() failed\n");
-                    rc = -ESRCH;
-                }
-                _fmutex_close(&__libc_gmtxExec);
+                __libc_spmRelease(pSelf);
+
+                /*
+                 * Done here.
+                 */
+                LIBCLOG_RETURN_INT(0);
             }
-            DosFreeThreadLocalMemory((PULONG)__libc_gpTLS);
-            __libc_gpTLS = NULL;
-        }
-        else
-            LIBC_ASSERTM_FAILED("DosAllocThreadLocalMemory() failed. rc=%d\n", rc);
-    }
+            else
+            {
+                LIBC_ASSERTM_FAILED("__libc_spmSelf() failed\n");
+                rc = -ESRCH;
+            }
+            _fmutex_close(&__libc_gmtxExec);
+        }
+        DosFreeThreadLocalMemory((PULONG)__libc_gpTLS);
+        __libc_gpTLS = NULL;
+    }
+    else
+        LIBC_ASSERTM_FAILED("DosAllocThreadLocalMemory() failed. rc=%d\n", rc);
+    /** @todo terminate SPM */
     LIBCLOG_ERROR_RETURN_INT(rc);
 }
@@ -142,4 +142,9 @@
     DosFreeThreadLocalMemory((PULONG)__libc_gpTLS);
     __libc_gpTLS = NULL;
+
+    /*
+     * Terminate SPM.
+     */
+    /** @todo terminate SPM */
 
     LIBCLOG_RETURN_VOID();
Index: /trunk/libc/src/kNIX/os2/libcfork.c
===================================================================
--- /trunk/libc/src/kNIX/os2/libcfork.c	(revision 2936)
+++ /trunk/libc/src/kNIX/os2/libcfork.c	(revision 2937)
@@ -350,9 +350,8 @@
         __libc_Timebomb();
 #endif
-
         /*
          * Find the SPM process.
          */
-        pProcess = __libc_spmSelf();
+        pProcess = __libc_spmSelf(1 /* auto init */);
         if (!pProcess)
         {
@@ -417,4 +416,5 @@
         {
             pTib->tib_pexchain = XcptRegRec.Core.prev_structure;
+            __libc_spmRelease(pProcess);
             LIBCLOG_RETURN_INT(0);
         }
@@ -425,4 +425,5 @@
          */
         pForkHandle = forkChlOpenHandle(pProcess->pvForkHandle);
+        __libc_spmRelease(pProcess);
         if (!pForkHandle)
         {
@@ -499,6 +500,5 @@
         /*
          * Don't deregister modules which has already been deregistered.
-         * Don't deregister if we're in shutting down the process (waste of time and
-         * SPM might already be shut down).
+         * Don't deregister if we're in shutting down the process (waste of time and SPM might already be shut down).
          */
         if (pModule->fFlags & __LIBC_FORKMODULE_FLAGS_DEREGISTERED)
@@ -521,9 +521,9 @@
          * Find the SPM process.
          */
-        __LIBC_PSPMPROCESS pProcess = __libc_spmSelf();
+        __LIBC_PSPMPROCESS pProcess = __libc_spmSelf(0 /* don't auto init */);
         if (!pProcess)
         {
             pTib->tib_pexchain = XcptRegRec.Core.prev_structure;
-            LIBC_ASSERTM_FAILED("can't find the process! weird!\n");
+            LIBC_ASSERTM_FAILED("can't find the process! weird!\n"); /* DLL termination order might be screwed up... */
             LIBCLOG_RETURN_VOID();
         }
@@ -559,4 +559,5 @@
         pModule->fFlags |= __LIBC_FORKMODULE_FLAGS_DEREGISTERED;
 
+        __libc_spmRelease(pProcess);
         pTib->tib_pexchain = XcptRegRec.Core.prev_structure;
         LIBCLOG_RETURN_VOID();
@@ -1566,10 +1567,12 @@
      */
     forkBthCloseHandle(pForkHandle, __LIBC_FORK_CTX_CHILD);
-    __LIBC_PSPMPROCESS pProcess = __libc_spmSelf();
+    __LIBC_PSPMPROCESS pProcess = __libc_spmSelf(0 /* no init */);
     LIBC_ASSERTM(pProcess, "No self process!!!\n");
     pProcess->pvForkHandle = NULL;
-
-    /*
-     * The return here will go back to the inline assmebly which called us in forkChlDoFork()
+    __libc_spmRelease(pProcess);
+
+
+    /*
+     * The return here will go back to the inline assembly which called us in forkChlDoFork()
      * and restore the stack pointer to the __libc_Back_processFork() and jump to the fork_ret
      * label in __libc_Back_processFork().
@@ -2217,5 +2220,5 @@
 {
     __LIBC_PFORKMODULE  pModules;
-    __LIBC_PSPMPROCESS  pProcessSelf = __libc_spmSelf();
+    __LIBC_PSPMPROCESS  pProcessSelf = __libc_spmSelf(0 /* no init */);
     if (pProcessSelf)
     {
Index: /trunk/libc/src/kNIX/os2/sharedpm.c
===================================================================
--- /trunk/libc/src/kNIX/os2/sharedpm.c	(revision 2936)
+++ /trunk/libc/src/kNIX/os2/sharedpm.c	(revision 2937)
@@ -93,4 +93,5 @@
 static int  spmRequestMutex(__LIBC_PSPMXCPTREGREC pRegRec);
 static int  spmReleaseMutex(__LIBC_PSPMXCPTREGREC pRegRec);
+static int  spmInit(__LIBC_PSPMXCPTREGREC pRegRec);
 static VOID APIENTRY spmExitList(ULONG ulReason);
 static void spmCleanup(void);
@@ -337,10 +338,11 @@
  *
  * @returns Pointer to the current process.
- * @returns NULL and errno on failure.
+ * @returns NULL on failure.
  * @remark  For this too __libc_spmRelease() must be called when done.
- */
-__LIBC_PSPMPROCESS __libc_spmSelf(void)
-{
-    LIBCLOG_ENTER("\n");
+ * @param   fAutoInit   Set if it's ok to automatically initialize SPM.
+ */
+__LIBC_PSPMPROCESS __libc_spmSelf(int fAutoInit)
+{
+    LIBCLOG_ENTER("fAutoInit=%d\n", fAutoInit);
     __LIBC_PSPMPROCESS pProcess;
 
@@ -350,27 +352,26 @@
 
     /*
-     * Check if we've already registered (we're allways registred).
-     * If we have we'll simply return.
+     * Read the cached variable.
+     * If the caller permits automatic initialization, we'll give it a shot.
      */
     pProcess = gpSPMSelf;
-    if (!pProcess)
-    {
-        __LIBC_SPMXCPTREGREC    RegRec;
-        if (spmRequestMutexErrno(&RegRec))
-            LIBCLOG_RETURN_P(NULL);
-        if (!gpSPMSelf)
-            pProcess = gpSPMSelf;
+    if (!pProcess && fAutoInit)
+    {
+        /* Don't try initialize unless we're in a virgin state. */
+        if (!gpSPMHdr && !gcNesting)
+        {
+            __LIBC_SPMXCPTREGREC RegRec;
+            int rc = spmInit(&RegRec);
+            if (!rc)
+            {
+                pProcess = gpSPMSelf;
+                spmReleaseMutex(&RegRec);
+                LIBC_ASSERT(pProcess);
+            }
+            else
+                LIBCLOG_ERROR("rc=%d\n", rc);
+        }
         else
-        {
-            PTIB                    pTib;
-            PPIB                    pPib;
-            PLINFOSEG               pLIS = GETLINFOSEG();
-            FS_VAR()
-            FS_SAVE_LOAD();
-            DosGetInfoBlocks(&pTib, &pPib);
-            pProcess = spmRegisterSelf(pPib->pib_ulpid, pPib->pib_ulppid, pLIS->sgCurrent);
-            FS_RESTORE();
-        }
-        spmReleaseMutex(&RegRec);
+            LIBCLOG_MSG("fAutoInit=%d gpSPMHdr=%p gcNesting=%d\n", fAutoInit, gpSPMHdr, gcNesting);
     }
 
@@ -1966,10 +1967,10 @@
     {
         /*
-         * Before exec we must ensure that we're opened
-         * for the logic below to work.
+         * Before exec we must ensure that we're opened for the logic below to work.
+         * (This is probably not necessary, but it doesn't hurt.)
          */
         case __LIBC_FORK_OP_EXEC_CHILD:
             if (!gpSPMSelf)
-                __libc_spmSelf();
+                __libc_spmSelf(1 /* auto init */);
             LIBCLOG_RETURN_INT(0);
 
@@ -2044,6 +2045,6 @@
 
 /**
- * Requests the shared mutex semphore and checks that we're
- * successfully initialized.
+ * Requests the shared mutex semphore and checks that we're successfully initialized.
+ *
  * @returns 0 on success.
  * @returns Negative error code (errno.h) on failure.
@@ -2077,9 +2078,9 @@
 
     /*
-     * Check if initatied.
+     * Check if initiated.
      */
     if (!ghmtxSPM || !gpSPMHdr)
     {
-        LIBC_ASSERTM_FAILED("not initialized!\n");
+        LIBC_ASSERTM_FAILED("not initialized! rc=%d\n", rc);
         DosUnsetExceptionHandler(&pRegRec->Core);
         FS_RESTORE();
@@ -2177,8 +2178,10 @@
  * first process using it.
  *
- * @returns 0 on success.
+ * @returns 0 on success, mutex owned.
  * @returns Negative error code (errno.h) on failure.
- */
-int __libc_spmInit(void)
+ *
+ * @param   pRegRec     Same as with spmRequestMutex().
+ */
+static int spmInit(__LIBC_PSPMXCPTREGREC pRegRec)
 {
     LIBCLOG_ENTER("\n");
@@ -2211,4 +2214,23 @@
 
     /*
+     * Install the exception handler.
+     */
+    FS_SAVE_LOAD();
+    pRegRec->Core.prev_structure   = (void *)~0;
+    pRegRec->Core.ExceptionHandler = spmXcptHandler;
+    DosSetExceptionHandler(&pRegRec->Core);
+
+    /*
+     * Check stack.
+     */
+    if (spmRequestMutexStackChecker())
+    {
+        DosUnsetExceptionHandler(&pRegRec->Core);
+        FS_RESTORE();
+        LIBC_ASSERTM_FAILED("Too little stack left!\n");
+        LIBCLOG_RETURN_INT(-EFAULT);
+    }
+
+    /*
      * Get current process id and parent process id
      * and install the exception handler.
@@ -2219,5 +2241,4 @@
      * Open or create mutex.
      */
-    FS_SAVE_LOAD();
     rc = DosOpenMutexSem((PCSZ)SPM_MUTEX_NAME, &ghmtxSPM);
     if (rc)
@@ -2230,4 +2251,5 @@
             if (rc2)
             {
+                DosUnsetExceptionHandler(&pRegRec->Core);
                 FS_RESTORE();
                 /* too bad, can create it for some reason. */
@@ -2335,8 +2357,6 @@
              */
             rc = DosExitList(0x9800 | EXLST_ADD, spmExitList);
+            LIBC_ASSERTM(!rc, "DosExitList failed with rc=%d\n", rc);
             FS_RESTORE();
-            DosReleaseMutexSem(ghmtxSPM);
-            DosExitMustComplete(&ul);
-            LIBC_ASSERTM(!rc, "DosExitList failed with rc=%d\n", rc);
             LIBCLOG_RETURN_INT(0);
         }
@@ -2356,4 +2376,5 @@
     gpSPMHdr = NULL;
     gpSPMSelf = NULL;
+    DosUnsetExceptionHandler(&pRegRec->Core);
     FS_RESTORE();
     rc = -__libc_back_native2errno(rc);
Index: /trunk/libc/src/libc/libc.def
===================================================================
--- /trunk/libc/src/libc/libc.def	(revision 2936)
+++ /trunk/libc/src/libc/libc.def	(revision 2937)
@@ -1953,5 +1953,5 @@
     "__std_getdirents" @1951
     "___libc_Back_ioFileControlStandard" @1952
-    "___libc_Back_termDll" @1953
+    ; dead "___libc_Back_termDll" @1953
     "___libc_ForkDeregisterModule" @1954
     "__std_nan" @1955
@@ -1960,6 +1960,5 @@
 
     ; new stuff 0.7
-    "__libc_back_envInitAsm" @1958
-    "__std_adjtime" @1959
-    "__std_getrusage" @1960
-    "__std_ttyname_r" @1961
+    "__std_adjtime" @1958
+    "__std_getrusage" @1959
+    "__std_ttyname_r" @1960
Index: /trunk/libc/src/libc/startup/initterm.c
===================================================================
--- /trunk/libc/src/libc/startup/initterm.c	(revision 2936)
+++ /trunk/libc/src/libc/startup/initterm.c	(revision 2937)
@@ -160,14 +160,4 @@
 
     /*
-     * The remaining bits are only done once.
-     *
-     * We currently IGNORE the posibility that two thread might be racing here and
-     * the loser begin able to call into LIBC while it's begin initialized.
-     */
-    const int32_t cRefs = __atomic_increment_s32(&g_cCrtUsers);
-    if (cRefs != 1)
-        LIBCLOG_RETURN_MSG(0, "ret 0 (g_cCrtUsers=%d)\n", cRefs);
-
-    /*
      * The backend must be initialized first.
      */
@@ -175,4 +165,14 @@
     if (!rc)
     {
+        /*
+         * The remaining bits are only done once.
+         *
+         * We currently IGNORE the posibility that two thread might be racing here and
+         * the loser begin able to call into LIBC while it's begin initialized.
+         */
+        const int32_t cRefs = __atomic_increment_s32(&g_cCrtUsers);
+        if (cRefs != 1)
+            LIBCLOG_RETURN_MSG(0, "ret 0 (g_cCrtUsers=%d)\n", cRefs);
+
         /*
          * Init the frontend.
@@ -182,11 +182,13 @@
          */
 
-        /* weak initializers. */
-        __ctordtorTerm1(&__crtinit1__);
-
-        LIBCLOG_RETURN_INT(0);
+        {
+            /* weak initializers. */
+            __ctordtorTerm1(&__crtinit1__);
+
+            LIBCLOG_RETURN_INT(0);
+        }
+        __atomic_decrement_s32(&g_cCrtUsers);
     }
 
-    __atomic_decrement_s32(&g_cCrtUsers);
     LIBCLOG_ERROR_RETURN_INT(rc);
 }
Index: /trunk/libc/src/libc/startup/os2/x86/dll0.s
===================================================================
--- /trunk/libc/src/libc/startup/os2/x86/dll0.s	(revision 2936)
+++ /trunk/libc/src/libc/startup/os2/x86/dll0.s	(revision 2937)
@@ -69,5 +69,5 @@
      * What are we in for?
      */
-    movl    8(%ebp), %eax
+    movl    0xc(%ebp), %eax
     orl     %eax, %eax
     je      dll0_init
