1
1
import os
2
2
import shutil
3
+ import signal
3
4
import tarfile
4
5
import importlib
6
+ import contextlib
5
7
from concurrent import futures
6
8
import re
7
9
11
13
from .textwrap import DALS
12
14
13
15
16
+ TIMEOUT = int (os .getenv ("TIMEOUT_BACKEND_TEST" , "180" )) # in seconds
17
+
18
+
14
19
class BuildBackendBase :
15
20
def __init__ (self , cwd = '.' , env = {}, backend_name = 'setuptools.build_meta' ):
16
21
self .cwd = cwd
@@ -31,10 +36,23 @@ def __getattr__(self, name):
31
36
def method (* args , ** kw ):
32
37
root = os .path .abspath (self .cwd )
33
38
caller = BuildBackendCaller (root , self .env , self .backend_name )
34
- return self .pool .submit (caller , name , * args , ** kw ).result ()
39
+ pid = None
40
+ try :
41
+ pid = self .pool .submit (os .getpid ).result (TIMEOUT )
42
+ return self .pool .submit (caller , name , * args , ** kw ).result (TIMEOUT )
43
+ except futures .TimeoutError :
44
+ self .pool .shutdown (wait = False ) # doesn't stop already running processes
45
+ self ._kill (pid )
46
+ pytest .xfail (f"Backend did not respond before timeout ({ TIMEOUT } s)" )
35
47
36
48
return method
37
49
50
+ def _kill (self , pid ):
51
+ if pid is None :
52
+ return
53
+ with contextlib .suppress (ProcessLookupError , OSError ):
54
+ os .kill (pid , signal .SIGTERM if os .name == "nt" else signal .SIGKILL )
55
+
38
56
39
57
class BuildBackendCaller (BuildBackendBase ):
40
58
def __init__ (self , * args , ** kwargs ):
0 commit comments