Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 01b5abb

Browse files
authored
gh-124666: Improve thread cleanup in test_android (#131427)
Ensures that failures in test setup don't result in dangling threads.
1 parent c1b42db commit 01b5abb

File tree

1 file changed

+26
-13
lines changed

1 file changed

+26
-13
lines changed

Lib/test/test_android.py

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -38,31 +38,41 @@ def logcat_thread():
3838
for line in self.logcat_process.stdout:
3939
self.logcat_queue.put(line.rstrip("\n"))
4040
self.logcat_process.stdout.close()
41+
4142
self.logcat_thread = Thread(target=logcat_thread)
4243
self.logcat_thread.start()
4344

44-
from ctypes import CDLL, c_char_p, c_int
45-
android_log_write = getattr(CDLL("liblog.so"), "__android_log_write")
46-
android_log_write.argtypes = (c_int, c_char_p, c_char_p)
47-
ANDROID_LOG_INFO = 4
48-
49-
# Separate tests using a marker line with a different tag.
50-
tag, message = "python.test", f"{self.id()} {time()}"
51-
android_log_write(
52-
ANDROID_LOG_INFO, tag.encode("UTF-8"), message.encode("UTF-8"))
53-
self.assert_log("I", tag, message, skip=True, timeout=5)
45+
try:
46+
from ctypes import CDLL, c_char_p, c_int
47+
android_log_write = getattr(CDLL("liblog.so"), "__android_log_write")
48+
android_log_write.argtypes = (c_int, c_char_p, c_char_p)
49+
ANDROID_LOG_INFO = 4
50+
51+
# Separate tests using a marker line with a different tag.
52+
tag, message = "python.test", f"{self.id()} {time()}"
53+
android_log_write(
54+
ANDROID_LOG_INFO, tag.encode("UTF-8"), message.encode("UTF-8"))
55+
self.assert_log("I", tag, message, skip=True)
56+
except:
57+
# If setUp throws an exception, tearDown is not automatically
58+
# called. Avoid leaving a dangling thread which would keep the
59+
# Python process alive indefinitely.
60+
self.tearDown()
61+
raise
5462

5563
def assert_logs(self, level, tag, expected, **kwargs):
5664
for line in expected:
5765
self.assert_log(level, tag, line, **kwargs)
5866

59-
def assert_log(self, level, tag, expected, *, skip=False, timeout=0.5):
60-
deadline = time() + timeout
67+
def assert_log(self, level, tag, expected, *, skip=False):
68+
deadline = time() + LOOPBACK_TIMEOUT
6169
while True:
6270
try:
6371
line = self.logcat_queue.get(timeout=(deadline - time()))
6472
except queue.Empty:
65-
self.fail(f"line not found: {expected!r}")
73+
raise self.failureException(
74+
f"line not found: {expected!r}"
75+
) from None
6676
if match := re.fullmatch(fr"(.)/{tag}: (.*)", line):
6777
try:
6878
self.assertEqual(level, match[1])
@@ -77,6 +87,9 @@ def tearDown(self):
7787
self.logcat_process.wait(LOOPBACK_TIMEOUT)
7888
self.logcat_thread.join(LOOPBACK_TIMEOUT)
7989

90+
# Avoid an irrelevant warning about threading._dangling.
91+
self.logcat_thread = None
92+
8093
@contextmanager
8194
def unbuffered(self, stream):
8295
stream.reconfigure(write_through=True)

0 commit comments

Comments
 (0)