@@ -11,6 +11,16 @@ cdef class UVProcess(UVHandle):
1111 self ._preexec_fn = None
1212 self ._restore_signals = True
1313
14+ cdef _close_process_handle(self ):
15+ # XXX: This is a workaround for a libuv bug:
16+ # - https://github.com/libuv/libuv/issues/1933
17+ # - https://github.com/libuv/libuv/pull/551
18+ if self ._handle is NULL :
19+ return
20+ self ._handle.data = NULL
21+ uv.uv_close(self ._handle, __uv_close_process_handle_cb)
22+ self ._handle = NULL # close callback will free() the memory
23+
1424 cdef _init(self , Loop loop, list args, dict env,
1525 cwd, start_new_session,
1626 _stdin, _stdout, _stderr, # std* can be defined as macros in C
@@ -79,16 +89,15 @@ cdef class UVProcess(UVHandle):
7989
8090 if _PyImport_ReleaseLock() < 0 :
8191 # See CPython/posixmodule.c for details
92+ self ._close_process_handle()
8293 if err < 0 :
8394 self ._abort_init()
8495 else :
8596 self ._close()
8697 raise RuntimeError (' not holding the import lock' )
8798
8899 if err < 0 :
89- if UVLOOP_DEBUG and uv.uv_is_active(self ._handle):
90- raise RuntimeError (
91- ' active uv_process_t handle after failed uv_spawn' )
100+ self ._close_process_handle()
92101 self ._abort_init()
93102 raise convert_error(err)
94103
@@ -754,3 +763,7 @@ cdef __socketpair():
754763 os_set_inheritable(fds[1 ], False )
755764
756765 return fds[0 ], fds[1 ]
766+
767+
768+ cdef void __uv_close_process_handle_cb(uv.uv_handle_t* handle) with gil:
769+ PyMem_RawFree(handle)
0 commit comments