From 32fe7efe508cc54b35f26f11b43e40c134715d37 Mon Sep 17 00:00:00 2001
From: Elliot Saba <staticfloat@gmail.com>
Date: Tue, 8 Feb 2022 10:41:35 -0800
Subject: [PATCH] Ensure that `open(::Function, ::Cmd)` waits for termination

On Windows, we observed occasional issues where an error within the
function callback to the `open(::Function, ::Cmd)` method would cause
problems due to assuming that the opened process had finished by the
time the `open()` call was finished.  In most cases this was true,
however on Windows, it was found that we need to explicitly `wait()`
upon the process object to ensure that all file handles held by the
subprocess were properly closed by the time `open()` is finished.
---
 base/process.jl | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/base/process.jl b/base/process.jl
index da73d10332b5d..0ab68e8181a9a 100644
--- a/base/process.jl
+++ b/base/process.jl
@@ -402,16 +402,25 @@ process failed, or if the process attempts to print anything to stdout.
 """
 function open(f::Function, cmds::AbstractCmd, args...; kwargs...)
     P = open(cmds, args...; kwargs...)
+    function waitkill(P::Process)
+        close(P)
+        # 0.1 seconds after we hope it dies (from closing stdio),
+        # we kill the process with SIGTERM (15)
+        local t = Timer(0.1) do t
+            process_running(P) && kill(P)
+        end
+        wait(P)
+        close(t)
+    end
     ret = try
         f(P)
     catch
-        kill(P)
-        close(P)
+        waitkill(P)
         rethrow()
     end
     close(P.in)
     if !eof(P.out)
-        close(P.out)
+        waitkill(P)
         throw(_UVError("open(do)", UV_EPIPE))
     end
     success(P) || pipeline_error(P)