timeout: Warn if the thread did not exit.

As noted in the docstring for this function, the timeout is
best-effort only -- if the thread is blocked in a syscall, it will not
service the exception until it returns.  It can also choose to catch
and ignore the TimeoutExpired; in either case it will still be running
even after the `timeout()` function returns.

Raising a vare TimeoutExpired it still somewhat accurate, but obscures
that the backend thread may still be running along merrily.  Notice
such cases, and log a warning about them.

(cherry picked from commit 3af2c8d9a3)
This commit is contained in:
Alex Vandiver
2022-04-05 11:34:56 -07:00
parent 44a3cd8dd3
commit 4a5204a967

View File

@@ -1,4 +1,5 @@
import ctypes
import logging
import sys
import threading
import time
@@ -82,6 +83,12 @@ def timeout(timeout: float, func: Callable[[], ResultT]) -> ResultT:
# Re-raise the exception we sent, if possible, so the
# stacktrace originates in the slow code
raise thread.exc_info[1].with_traceback(thread.exc_info[2])
# If we don't have that for some reason (e.g. we failed to
# kill it), just raise from here; the thread _may still be
# running_ because it failed to see any of our exceptions, and
# we just ignore it.
if thread.is_alive():
logging.warning("Failed to time out backend thread")
raise TimeoutExpired
if thread.exc_info[1] is not None: