@@ -10,7 +10,6 @@ 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
14
13
15
14
cdef _init(self , Loop loop, list args, dict env,
16
15
cwd, start_new_session,
@@ -115,6 +114,14 @@ cdef class UVProcess(UVHandle):
115
114
# after the process is finished.
116
115
self ._pid = (< uv.uv_process_t* > self ._handle).pid
117
116
117
+ # Track the process handle (create a strong ref to it)
118
+ # to guarantee that __dealloc__ doesn't happen in an
119
+ # uncontrolled fashion. We want to wait until the process
120
+ # exits and libuv calls __uvprocess_on_exit_callback,
121
+ # which will call `UVProcess._close()`, which will, in turn,
122
+ # untrack this handle.
123
+ self ._loop._track_process(self )
124
+
118
125
for fd in restore_inheritable:
119
126
os_set_inheritable(fd, False )
120
127
@@ -133,7 +140,7 @@ cdef class UVProcess(UVHandle):
133
140
exc_name, exc_msg = errpipe_data.split(b' :' , 1 )
134
141
exc_name = exc_name.decode()
135
142
exc_msg = exc_msg.decode()
136
- except :
143
+ except Exception :
137
144
self ._close()
138
145
raise subprocess_SubprocessError(
139
146
' Bad exception data from child: {!r}' .format(
@@ -306,8 +313,6 @@ cdef class UVProcess(UVHandle):
306
313
cdef _kill(self , int signum):
307
314
cdef int err
308
315
self ._ensure_alive()
309
- if signum in {uv.SIGKILL, uv.SIGTERM}:
310
- self ._kill_requested = True
311
316
err = uv.uv_process_kill(< uv.uv_process_t* > self ._handle, signum)
312
317
if err < 0 :
313
318
raise convert_error(err)
@@ -323,6 +328,13 @@ cdef class UVProcess(UVHandle):
323
328
324
329
self ._close()
325
330
331
+ cdef _close(self ):
332
+ try :
333
+ if self ._loop is not None :
334
+ self ._loop._untrack_process(self )
335
+ finally :
336
+ UVHandle._close(self )
337
+
326
338
327
339
DEF _CALL_PIPE_DATA_RECEIVED = 0
328
340
DEF _CALL_PIPE_CONNECTION_LOST = 1
@@ -360,6 +372,8 @@ cdef class UVProcessTransport(UVProcess):
360
372
waiter.set_result(self ._returncode)
361
373
self ._exit_waiters.clear()
362
374
375
+ self ._close()
376
+
363
377
cdef _check_proc(self ):
364
378
if not self ._is_alive() or self ._returncode is not None :
365
379
raise ProcessLookupError()
@@ -537,11 +551,6 @@ cdef class UVProcessTransport(UVProcess):
537
551
else :
538
552
self ._pending_calls.append((_CALL_CONNECTION_LOST, None , None ))
539
553
540
- cdef _warn_unclosed(self ):
541
- if self ._kill_requested:
542
- return
543
- super ()._warn_unclosed()
544
-
545
554
def __stdio_inited (self , waiter , stdio_fut ):
546
555
exc = stdio_fut.exception()
547
556
if exc is not None :
@@ -556,21 +565,6 @@ cdef class UVProcessTransport(UVProcess):
556
565
< method1_t> self ._call_connection_made,
557
566
self , waiter))
558
567
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
-
574
568
@staticmethod
575
569
cdef UVProcessTransport new(Loop loop, protocol, args, env,
576
570
cwd, start_new_session,
0 commit comments