33'''
44import re
55import os
6+ import sys
67from os .path import splitext , join
78import subprocess
89from datetime import datetime
@@ -773,13 +774,21 @@ def get_file_contents(filepath):
773774 return ''
774775
775776def run_subtool_noread (cmd , cwd = None , timeout = None ):
776- """Run external command without reading output; kill if it runs longer than timeout (seconds) .
777+ """Run external command without reading output; kill whole process group on timeout.
777778 Returns (returncode, timed_out: bool).
778779 """
779780
780781 if not cwd :
781782 cwd = os .getcwd ()
782783
784+ # Platform-specific flags
785+ if sys .platform == "win32" :
786+ creationflags = subprocess .CREATE_NEW_PROCESS_GROUP
787+ preexec_fn = None
788+ else :
789+ creationflags = 0
790+ preexec_fn = os .setsid # start new session -> new process group
791+
783792 try :
784793 process = subprocess .Popen (
785794 cmd ,
@@ -789,21 +798,30 @@ def run_subtool_noread(cmd, cwd=None, timeout=None):
789798 shell = True ,
790799 universal_newlines = True ,
791800 cwd = cwd ,
801+ preexec_fn = preexec_fn ,
802+ creationflags = creationflags ,
792803 )
793804
794805 try :
795- # communicate supports timeout (Python 3.3+)
796806 process .communicate (timeout = timeout )
797807 return process .returncode , False
798808 except subprocess .TimeoutExpired :
799- # force kill if still alive
809+ # Kill the whole process group
800810 try :
801- process .kill () # SIGKILL on Unix
811+ if sys .platform == "win32" :
812+ # send CTRL_BREAK_EVENT to the process group
813+ process .send_signal (signal .CTRL_BREAK_EVENT )
814+ else :
815+ os .killpg (os .getpgid (process .pid ), signal .SIGKILL )
802816 except Exception :
803- pass
817+ # fallback to killing the process
818+ try :
819+ process .kill ()
820+ except Exception :
821+ pass
822+ # Wait for termination
804823 process .wait ()
805-
806- return process .returncode if process .returncode is not None else - 1 , True
824+ return process .returncode if process .returncode is not None else - 1 , True
807825
808826 except Exception as e :
809827 # unicode/read error safe-guard
0 commit comments