@@ -812,6 +812,27 @@ def _kill_process(self, method, *args):
812812 getattr (p , method )(* args )
813813 return p
814814
815+ def _kill_dead_process (self , method , * args ):
816+ # Do not inherit file handles from the parent.
817+ # It should fix failures on some platforms.
818+ p = subprocess .Popen ([sys .executable , "-c" , """if 1:
819+ import sys, time
820+ sys.stdout.write('x\\ n')
821+ sys.stdout.flush()
822+ """ ],
823+ close_fds = True ,
824+ stdin = subprocess .PIPE ,
825+ stdout = subprocess .PIPE ,
826+ stderr = subprocess .PIPE )
827+ # Wait for the interpreter to be completely initialized before
828+ # sending any signal.
829+ p .stdout .read (1 )
830+ # The process should end after this
831+ time .sleep (1 )
832+ # This shouldn't raise even though the child is now dead
833+ getattr (p , method )(* args )
834+ p .communicate ()
835+
815836 def test_send_signal (self ):
816837 p = self ._kill_process ('send_signal' , signal .SIGINT )
817838 _ , stderr = p .communicate ()
@@ -830,6 +851,18 @@ def test_terminate(self):
830851 self .assertStderrEqual (stderr , '' )
831852 self .assertEqual (p .wait (), - signal .SIGTERM )
832853
854+ def test_send_signal_dead (self ):
855+ # Sending a signal to a dead process
856+ self ._kill_dead_process ('send_signal' , signal .SIGINT )
857+
858+ def test_kill_dead (self ):
859+ # Killing a dead process
860+ self ._kill_dead_process ('kill' )
861+
862+ def test_terminate_dead (self ):
863+ # Terminating a dead process
864+ self ._kill_dead_process ('terminate' )
865+
833866 def check_close_std_fds (self , fds ):
834867 # Issue #9905: test that subprocess pipes still work properly with
835868 # some standard fds closed
@@ -1126,6 +1159,31 @@ def _kill_process(self, method, *args):
11261159 returncode = p .wait ()
11271160 self .assertNotEqual (returncode , 0 )
11281161
1162+ def _kill_dead_process (self , method , * args ):
1163+ p = subprocess .Popen ([sys .executable , "-c" , """if 1:
1164+ import sys, time
1165+ sys.stdout.write('x\\ n')
1166+ sys.stdout.flush()
1167+ sys.exit(42)
1168+ """ ],
1169+ stdin = subprocess .PIPE ,
1170+ stdout = subprocess .PIPE ,
1171+ stderr = subprocess .PIPE )
1172+ self .addCleanup (p .stdout .close )
1173+ self .addCleanup (p .stderr .close )
1174+ self .addCleanup (p .stdin .close )
1175+ # Wait for the interpreter to be completely initialized before
1176+ # sending any signal.
1177+ p .stdout .read (1 )
1178+ # The process should end after this
1179+ time .sleep (1 )
1180+ # This shouldn't raise even though the child is now dead
1181+ getattr (p , method )(* args )
1182+ _ , stderr = p .communicate ()
1183+ self .assertStderrEqual (stderr , b'' )
1184+ rc = p .wait ()
1185+ self .assertEqual (rc , 42 )
1186+
11291187 def test_send_signal (self ):
11301188 self ._kill_process ('send_signal' , signal .SIGTERM )
11311189
@@ -1135,6 +1193,15 @@ def test_kill(self):
11351193 def test_terminate (self ):
11361194 self ._kill_process ('terminate' )
11371195
1196+ def test_send_signal_dead (self ):
1197+ self ._kill_dead_process ('send_signal' , signal .SIGTERM )
1198+
1199+ def test_kill_dead (self ):
1200+ self ._kill_dead_process ('kill' )
1201+
1202+ def test_terminate_dead (self ):
1203+ self ._kill_dead_process ('terminate' )
1204+
11381205
11391206@unittest .skipUnless (getattr (subprocess , '_has_poll' , False ),
11401207 "poll system call not supported" )
0 commit comments