@@ -10,6 +10,7 @@ cdef class UVProcess(UVHandle):
10
10
self ._fds_to_close = set ()
11
11
self ._preexec_fn = None
12
12
self ._restore_signals = True
13
+ self ._kill_requested = False
13
14
14
15
cdef _init(self , Loop loop, list args, dict env,
15
16
cwd, start_new_session,
@@ -182,7 +183,7 @@ cdef class UVProcess(UVHandle):
182
183
' UVProcess._close_after_spawn called after uv_spawn' )
183
184
self ._fds_to_close.add(fd)
184
185
185
- def __dealloc__ (self ):
186
+ cdef _dealloc_impl (self ):
186
187
if self .uv_opt_env is not NULL :
187
188
PyMem_RawFree(self .uv_opt_env)
188
189
self .uv_opt_env = NULL
@@ -191,6 +192,8 @@ cdef class UVProcess(UVHandle):
191
192
PyMem_RawFree(self .uv_opt_args)
192
193
self .uv_opt_args = NULL
193
194
195
+ UVHandle._dealloc_impl(self )
196
+
194
197
cdef char ** __to_cstring_array(self , list arr):
195
198
cdef:
196
199
int i
@@ -303,6 +306,8 @@ cdef class UVProcess(UVHandle):
303
306
cdef _kill(self , int signum):
304
307
cdef int err
305
308
self ._ensure_alive()
309
+ if signum in {uv.SIGKILL, uv.SIGTERM}:
310
+ self ._kill_requested = True
306
311
err = uv.uv_process_kill(< uv.uv_process_t* > self ._handle, signum)
307
312
if err < 0 :
308
313
raise convert_error(err)
@@ -532,6 +537,11 @@ cdef class UVProcessTransport(UVProcess):
532
537
else :
533
538
self ._pending_calls.append((_CALL_CONNECTION_LOST, None , None ))
534
539
540
+ cdef _warn_unclosed(self ):
541
+ if self ._kill_requested:
542
+ return
543
+ super ()._warn_unclosed()
544
+
535
545
def __stdio_inited (self , waiter , stdio_fut ):
536
546
exc = stdio_fut.exception()
537
547
if exc is not None :
@@ -546,6 +556,21 @@ cdef class UVProcessTransport(UVProcess):
546
556
< method1_t> self ._call_connection_made,
547
557
self , waiter))
548
558
559
+ cdef _dealloc_impl(self ):
560
+ cdef int fix_needed
561
+
562
+ if UVLOOP_DEBUG:
563
+ # Check when __dealloc__ will simply call uv.uv_close()
564
+ # directly, thus *skipping* incrementing the debug counter;
565
+ # we need to fix that.
566
+ fix_needed = not self ._closed and self ._inited
567
+
568
+ UVProcess._dealloc_impl(self )
569
+
570
+ if UVLOOP_DEBUG and fix_needed and self ._kill_requested:
571
+ self ._loop._debug_handles_closed.update([
572
+ self .__class__.__name__ ])
573
+
549
574
@staticmethod
550
575
cdef UVProcessTransport new(Loop loop, protocol, args, env,
551
576
cwd, start_new_session,
@@ -628,7 +653,14 @@ cdef class UVProcessTransport(UVProcess):
628
653
if self ._stderr is not None :
629
654
self ._stderr.close()
630
655
631
- self ._close()
656
+ if self ._returncode is not None :
657
+ # The process is dead, just close the UV handle.
658
+ #
659
+ # (If "self._returncode is None", the process should have been
660
+ # killed already and we're just waiting for a SIGCHLD; after
661
+ # which the transport will be GC'ed and the uvhandle will be
662
+ # closed in UVHandle.__dealloc__.)
663
+ self ._close()
632
664
633
665
def get_extra_info (self , name , default = None ):
634
666
return default
0 commit comments