Index: trunk/src/emx/src/lib/lgpl/posix/spawn_int.h
===================================================================
--- trunk/src/emx/src/lib/lgpl/posix/spawn_int.h	(revision 1051)
+++ trunk/src/emx/src/lib/lgpl/posix/spawn_int.h	(revision 1052)
@@ -28,10 +28,4 @@
     } open_action;
   } action;
-
-#ifdef __EMX__
-  /* reserve space for saving the handle which we're closing / replacing. */
-  int fd_saved;                         /* handle to the saved file. -1 if N/A. */
-  int fd_saved_coe;                     /* original close on exec flag. */
-#endif
 };
 
Index: trunk/src/emx/src/lib/lgpl/sysdeps/os2/__spawni.c
===================================================================
--- trunk/src/emx/src/lib/lgpl/sysdeps/os2/__spawni.c	(revision 1051)
+++ trunk/src/emx/src/lib/lgpl/sysdeps/os2/__spawni.c	(revision 1052)
@@ -26,4 +26,7 @@
 
 
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
 #include <stdlib.h>
 #include <string.h>
@@ -34,5 +37,20 @@
 #include <process.h>
 #include <emx/io.h>
+#include <emx/umalloc.h>
+#ifdef DEBUG
+#include <assert.h>
+#endif
 #include "../../posix/spawn_int.h"
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+typedef struct RestoreAction
+{
+    int fdClose;                        /* handle to close before restoring fdRestore. */
+    int fdRestore;                      /* fd which fdSaved is a saved version of. */
+    int fdSaved;                        /* close-on-exec dup of fdRestore. */
+    int fSavedCoE;                      /* the original close-on-exec flag. */
+} RESTOREACTION, *PRESTOREACTION;
 
 /**
@@ -49,20 +67,24 @@
  *                      Set to -1 on failure.
  */
-static int save_handle(int fdToSave, int *pfdMin, int *pfdSaved, int *pfCoE)
+static int save_handle(int fdToSave, int *pfdMin, PRESTOREACTION pRAction)
 {
-    int fCoE;
     int fdSaved;
-
-    *pfCoE = *pfdSaved = -1;
+    int fSavedCoE;
+
+    pRAction->fdRestore = - 1;
+    pRAction->fdSaved = -1;
+    pRAction->fSavedCoE = -1;
+    if (!__libc_FH(fdToSave))
+        return 0;                       /* no such handle. */
 
     /* Get close on exec flag. */
-    fCoE = fcntl(fdToSave, F_GETFD);
-    if (fCoE < 0)
+    fSavedCoE = fcntl(fdToSave, F_GETFD);
+    if (fSavedCoE < 0)
         return -1;
 
     /* find free handle and duplicate fdToSave onto it */
-    while (!__libc_FH(*pfdMin))
+    while (__libc_FH(*pfdMin))
         (*pfdMin)++;
-    if (*pfdMin >= 65536)
+    if (*pfdMin >= 0x10000)
         return -1;
     fdSaved = dup2(fdToSave, *pfdMin);
@@ -71,5 +93,5 @@
 
     /* marke it close on exit. */
-    if (    fCoE
+    if (    fSavedCoE
         &&  fcntl(fdSaved, F_SETFD, FD_CLOEXEC) < 0)
     {
@@ -78,6 +100,7 @@
         return -1;
     }
-    *pfCoE      = fCoE;
-    *pfdSaved   = fdSaved;
+    pRAction->fdRestore = fdToSave;
+    pRAction->fdSaved   = fdSaved;
+    pRAction->fSavedCoE = fSavedCoE;
     return 0;
 }
@@ -88,21 +111,38 @@
  *
  * @param   fdToRestore The original handle which is to be restored.
- * @param   pfdSaved    Pointer to the save handle.
- *                      This will be set to -1.
- * @param   pfCoE       Pointer to the
- *                      This will be set to -1.
+ * @param   pRAction    Restore action structure.
  */
-static void restore_handle(int fdToRestore, int *pfdSaved, int *pfCoE)
+static void restore_handle(PRESTOREACTION pRAction)
 {
-    int saved_errno;
-    if (*pfdSaved == -1)
-        return;
-    saved_errno = errno;
-
-    dup2(*pfdSaved, fdToRestore);
-    close(*pfdSaved);
-    fcntl(fdToRestore, F_SETFD, *pfCoE);
-    *pfdSaved = -1;
-    *pfCoE = -1;
+    int saved_errno = errno;
+
+    if (pRAction->fdClose >= 0)
+    {
+#ifndef DEBUG
+        close(pRAction->fdClose);
+#else
+        if (close(pRAction->fdClose))
+            assert(!"__spawni: restore close() failed");
+#endif
+        pRAction->fdClose = -1;
+    }
+
+    if (pRAction->fdSaved >= 0)
+    {
+#ifndef DEBUG
+        dup2(pRAction->fdSaved, pRAction->fdRestore);
+        close(pRAction->fdSaved);
+        fcntl(pRAction->fdRestore, F_SETFD, pRAction->fSavedCoE);
+#else
+        if (dup2(pRAction->fdSaved, pRAction->fdRestore) < 0)
+            assert(!"__spawni: restore dup2() failed");
+        if (close(pRAction->fdSaved) < 0)
+            assert(!"__spawni: restore close(saved) failed");
+        if (fcntl(pRAction->fdRestore, F_SETFD, pRAction->fSavedCoE) < 0)
+            assert(!"__spawni: restore fcntl() failed");
+#endif
+        pRAction->fdSaved = -1;
+        pRAction->fSavedCoE = -1;
+    }
 
     errno = saved_errno;
@@ -120,7 +160,8 @@
     int use_path)
 {
-    int         iFileAction = 0;        /* where to start cleaning up file actions from.  */
-    int         rc;                     /* result. */
-    pid_t       pidChild;
+    int             iFileAction = 0;    /* where to start cleaning up file actions from.  */
+    PRESTOREACTION  paRestore = NULL;
+    int             rc;                 /* result. */
+    pid_t           pidChild;
 #if 0 /* requires some process management from LIBC */
     unsigned    fFlags = attrp ? attrp->__flags : 0;
@@ -170,9 +211,9 @@
 
         /* Verify handles and predict what open() and dup2() will return so we can
-           find the min save handle number. */
+           find the min save handle number.
+           Note. we're counting too many opens here... but who cares. */
         for (i = cOpens = 0; !rc && i < file_actions->__used; ++i)
         {
             struct __spawn_action  *pAction = (struct __spawn_action *)&file_actions->__actions[i]; /* nasty - const */
-            pAction->fd_saved = pAction->fd_saved_coe = -1;
             switch (pAction->tag)
             {
@@ -199,5 +240,13 @@
         }
 
-        for (fdMin = 0; cOpens >= 0; fdMin++)
+        paRestore = _hmalloc(sizeof(RESTOREACTION) * file_actions->__used);
+        if (!paRestore)
+        {
+            /* TODO: release the file handle table lock. */
+            return -1;
+        }
+        memset(paRestore, -1, sizeof(RESTOREACTION) * file_actions->__used);
+
+        for (fdMin = 0; cOpens >= 0 && fdMin < 0x10000; fdMin++)
         {
             int fClosed;
@@ -217,4 +266,6 @@
                         break;
                     case spawn_do_open:
+                        if (pAction->action.open_action.fd == fdMin)
+                            fDuped = 1;
                         break;
                 }
@@ -225,5 +276,5 @@
                 continue;
             /* if not closed or not being freed we cannot use it. */
-            if (!fClosed || __libc_FH(fdMin))
+            if (!fClosed && __libc_FH(fdMin))
                 continue;
             /* it's either closed or free */
@@ -235,14 +286,15 @@
         {
             struct __spawn_action  *pAction = (struct __spawn_action *)&file_actions->__actions[i]; /* nasty - const */
+            PRESTOREACTION          pRAction = &paRestore[i];
 
             switch (pAction->tag)
             {
                 case spawn_do_close:
-                    rc = save_handle(pAction->action.close_action.fd, &fdMin, &pAction->fd_saved_coe, &pAction->fd_saved_coe);
+                    rc = save_handle(pAction->action.close_action.fd, &fdMin, pRAction);
                     if (rc)
                         break;
                     if (close(pAction->action.close_action.fd))
                     {
-                        restore_handle(pAction->action.close_action.fd, &pAction->fd_saved_coe, &pAction->fd_saved_coe);
+                        restore_handle(pRAction);
                         rc = -1;
                     }
@@ -250,10 +302,25 @@
 
                 case spawn_do_open:
-                    pAction->fd_saved = open(pAction->action.open_action.path,
-                                             pAction->action.open_action.mode,
-                                             pAction->action.open_action.oflag);
-                    if (    pAction->fd_saved < 0
-                        ||  pAction->fd_saved != pAction->action.open_action.fd)
-                        rc = -1;
+                    pRAction->fdClose = open(pAction->action.open_action.path,
+                                             pAction->action.open_action.oflag,
+                                             pAction->action.open_action.mode);
+                    if (pRAction->fdClose < 0)
+                        rc = -1;
+                    else if (   pRAction->fdClose != pAction->action.open_action.fd
+                             && pAction->action.open_action.fd != -1   /* -1 is not standard */)
+                    {
+                        int fd = pRAction->fdClose;
+                        pRAction->fdClose = -1;
+                        rc = save_handle(pAction->action.open_action.fd, &fdMin, pRAction);
+                        if (!rc)
+                        {
+                            if (dup2(fd, pAction->action.open_action.fd) < 0)
+                            {
+                                restore_handle(pRAction);
+                                rc = -1;
+                            }
+                        }
+                        close(fd);
+                    }
                     break;
 
@@ -261,12 +328,13 @@
                     if (pAction->action.dup2_action.newfd != -1)
                     {
-                        rc = save_handle(pAction->action.dup2_action.newfd, &fdMin, &pAction->fd_saved_coe, &pAction->fd_saved_coe);
+                        rc = save_handle(pAction->action.dup2_action.newfd, &fdMin, pRAction);
                         if (rc)
                             break;
                     }
 
-                    if (dup2(pAction->action.dup2_action.fd, pAction->action.dup2_action.newfd) < 0)
+                    pRAction->fdClose = dup2(pAction->action.dup2_action.fd, pAction->action.dup2_action.newfd);
+                    if (pRAction->fdClose < 0)
                     {
-                        restore_handle(pAction->action.dup2_action.newfd, &pAction->fd_saved_coe, &pAction->fd_saved_coe);
+                        restore_handle(pRAction);
                         rc = -1;
                     }
@@ -305,23 +373,10 @@
      * Restore the file handles.
      */
-    if (file_actions)
+    if (paRestore)
     {
         int save_errno = errno;
         while (iFileAction-- > 0)
-        {
-            struct __spawn_action  *pAction = (struct __spawn_action *)&file_actions->__actions[iFileAction]; /* nasty - const */
-            switch (pAction->tag)
-            {
-                case spawn_do_close:
-                    restore_handle(pAction->action.close_action.fd, &pAction->fd_saved_coe, &pAction->fd_saved_coe);
-                    break;
-                case spawn_do_open:
-                    close(pAction->fd_saved);
-                    break;
-                case spawn_do_dup2:
-                    restore_handle(pAction->action.dup2_action.newfd, &pAction->fd_saved_coe, &pAction->fd_saved_coe);
-                    break;
-            }
-        }
+            restore_handle(&paRestore[iFileAction]);
+        free(paRestore);
         errno = save_errno;
     }
