bpo-38502: regrtest uses process groups if available (GH-16829) · python/cpython@ecb035c (original) (raw)

`@@ -3,6 +3,7 @@

`

3

3

`import json

`

4

4

`import os

`

5

5

`import queue

`

``

6

`+

import signal

`

6

7

`import subprocess

`

7

8

`import sys

`

8

9

`import threading

`

31

32

`# Time to wait until a worker completes: should be immediate

`

32

33

`JOIN_TIMEOUT = 30.0 # seconds

`

33

34

``

``

35

`+

USE_PROCESS_GROUP = (hasattr(os, "setsid") and hasattr(os, "killpg"))

`

``

36

+

34

37

``

35

38

`def must_stop(result, ns):

`

36

39

`if result.result == INTERRUPTED:

`

`@@ -59,12 +62,16 @@ def run_test_in_subprocess(testname, ns):

`

59

62

`# Running the child from the same working directory as regrtest's original

`

60

63

`# invocation ensures that TEMPDIR for the child is the same when

`

61

64

`# sysconfig.is_python_build() is true. See issue 15300.

`

``

65

`+

kw = {}

`

``

66

`+

if USE_PROCESS_GROUP:

`

``

67

`+

kw['start_new_session'] = True

`

62

68

`return subprocess.Popen(cmd,

`

63

69

`stdout=subprocess.PIPE,

`

64

70

`stderr=subprocess.PIPE,

`

65

71

`universal_newlines=True,

`

66

72

`close_fds=(os.name != 'nt'),

`

67

``

`-

cwd=support.SAVEDCWD)

`

``

73

`+

cwd=support.SAVEDCWD,

`

``

74

`+

**kw)

`

68

75

``

69

76

``

70

77

`def run_tests_worker(ns, test_name):

`

`@@ -149,16 +156,24 @@ def _kill(self):

`

149

156

`return

`

150

157

`self._killed = True

`

151

158

``

152

``

`-

print(f"Kill {self}", file=sys.stderr, flush=True)

`

``

159

`+

if USE_PROCESS_GROUP:

`

``

160

`+

what = f"{self} process group"

`

``

161

`+

else:

`

``

162

`+

what = f"{self}"

`

``

163

+

``

164

`+

print(f"Kill {what}", file=sys.stderr, flush=True)

`

153

165

`try:

`

154

``

`-

popen.kill()

`

``

166

`+

if USE_PROCESS_GROUP:

`

``

167

`+

os.killpg(popen.pid, signal.SIGKILL)

`

``

168

`+

else:

`

``

169

`+

popen.kill()

`

155

170

`except ProcessLookupError:

`

156

``

`-

Process completed, the TestWorkerProcess thread read its exit

`

157

``

`-

status, but Popen.send_signal() read the returncode just before

`

158

``

`-

Popen.wait() set returncode.

`

``

171

`+

popen.kill(): the process completed, the TestWorkerProcess thread

`

``

172

`+

read its exit status, but Popen.send_signal() read the returncode

`

``

173

`+

just before Popen.wait() set returncode.

`

159

174

`pass

`

160

175

`except OSError as exc:

`

161

``

`-

print_warning(f"Failed to kill {self}: {exc!r}")

`

``

176

`+

print_warning(f"Failed to kill {what}: {exc!r}")

`

162

177

``

163

178

`def stop(self):

`

164

179

`# Method called from a different thread to stop this thread

`