> 2020-11-30  Bruno Haible  <br...@clisp.org>
> 
>       execute, spawn-pipe: Make multithread-safe on native Windows.

Oops, there was a mistake in this change: it caused two tests
(test-pipe-filter-ii1.sh, test-pipe-filter-gi1.sh) to hang. The hang is
a symptom that there is one extra handle left open to a pipe. (The OS
knows that a pipe is done when there is no reader or no writer any more.)
This patch fixes it.


2020-12-13  Bruno Haible  <br...@clisp.org>

        spawn-pipe: Fix hanging processes on Windows (regression 2020-11-30).
        * lib/spawn-pipe.c (create_pipe): After spawning the subprocess, close
        the stdin_handle and/or stdout_handle.

diff --git a/lib/spawn-pipe.c b/lib/spawn-pipe.c
index ba07d20..bd34959 100644
--- a/lib/spawn-pipe.c
+++ b/lib/spawn-pipe.c
@@ -222,6 +222,8 @@ create_pipe (const char *progname,
   bool must_close_ofd0 = pipe_stdin;
 
   /* Create standard file handles of child process.  */
+  HANDLE stdin_handle = INVALID_HANDLE_VALUE;
+  HANDLE stdout_handle = INVALID_HANDLE_VALUE;
   nulloutfd = -1;
   stdinfd = -1;
   stdoutfd = -1;
@@ -243,7 +245,7 @@ create_pipe (const char *progname,
        to pass NULL, the child process would inherit a copy of the environment
        block - ignoring the effects of putenv() and [un]setenv().  */
     {
-      HANDLE stdin_handle =
+      stdin_handle =
         (HANDLE) _get_osfhandle (pipe_stdin ? ofd[0] :
                                  prog_stdin == NULL ? STDIN_FILENO : stdinfd);
       if (pipe_stdin)
@@ -261,7 +263,7 @@ create_pipe (const char *progname,
           close (ofd[0]); /* implies CloseHandle (stdin_handle); */
           stdin_handle = duplicate;
         }
-      HANDLE stdout_handle =
+      stdout_handle =
         (HANDLE) _get_osfhandle (pipe_stdout ? ifd[1] :
                                  prog_stdout == NULL ? STDOUT_FILENO : 
stdoutfd);
       if (pipe_stdout)
@@ -306,10 +308,22 @@ create_pipe (const char *progname,
   if (nulloutfd >= 0)
     close (nulloutfd);
 
-  if (must_close_ofd0)
-    close (ofd[0]);
-  if (must_close_ifd1)
-    close (ifd[1]);
+  if (pipe_stdin)
+    {
+      if (must_close_ofd0)
+        close (ofd[0]);
+      else
+        if (stdin_handle != INVALID_HANDLE_VALUE)
+          CloseHandle (stdin_handle);
+    }
+  if (pipe_stdout)
+    {
+      if (must_close_ifd1)
+        close (ifd[1]);
+      else
+        if (stdout_handle != INVALID_HANDLE_VALUE)
+          CloseHandle (stdout_handle);
+    }
 
 # else /* __KLIBC__ */
   if (!(directory == NULL && strcmp (directory, ".") == 0))


Reply via email to