|
16 | 16 | from pathlib import Path |
17 | 17 | from typing import List |
18 | 18 | from urllib.error import URLError |
19 | | -from concurrent.futures import ThreadPoolExecutor, TimeoutError |
20 | 19 | import qdarkstyle |
| 20 | +import multiprocessing |
21 | 21 |
|
22 | 22 | import deeplabcut |
23 | 23 | from deeplabcut import auxiliaryfunctions, VERSION, compat |
|
42 | 42 |
|
43 | 43 |
|
44 | 44 | def call_with_timeout(func, timeout, *args, **kwargs): |
45 | | - with ThreadPoolExecutor(max_workers=1) as executor: |
46 | | - future = executor.submit(func, *args, **kwargs) |
47 | | - return future.result(timeout=timeout) |
| 45 | + def wrapper(queue, *args, **kwargs): |
| 46 | + try: |
| 47 | + result = func(*args, **kwargs) |
| 48 | + queue.put(result) # Pass the result back via the queue |
| 49 | + except Exception as e: |
| 50 | + queue.put(e) # Pass any exception back via the queue |
| 51 | + |
| 52 | + queue = multiprocessing.Queue() |
| 53 | + process = multiprocessing.Process(target=wrapper, args=(queue, *args), kwargs=kwargs) |
| 54 | + process.start() |
| 55 | + process.join(timeout) |
| 56 | + |
| 57 | + if process.is_alive(): |
| 58 | + process.terminate() # Forcefully terminate the process |
| 59 | + process.join() |
| 60 | + raise TimeoutError(f"Function {func.__name__} did not complete within {timeout} seconds.") |
| 61 | + |
| 62 | + if not queue.empty(): |
| 63 | + result = queue.get() |
| 64 | + if isinstance(result, Exception): |
| 65 | + raise result # Re-raise the exception if it occurred in the function |
| 66 | + return result |
| 67 | + else: |
| 68 | + raise TimeoutError(f"Function {func.__name__} completed but did not return a result.") |
48 | 69 |
|
49 | 70 |
|
50 | 71 | def _check_for_updates(silent=True): |
|
0 commit comments