From 43303e362e3a7e2d96747d881021a14c7f7e3d0b Mon Sep 17 00:00:00 2001 From: Malcolm Smith Date: Thu, 12 Sep 2024 06:52:07 +0100 Subject: [PATCH] gh-116622: Switch test_stress_delivery_simultaneous from SIGUSR1 to SIGUSR2 (#123981) Use SIGUSR1 instead of SIGUSR2 to improve reliability of signal stress test on Android. --- Android/testbed/app/src/main/python/main.py | 22 ++++++++++++++++++--- Lib/test/test_signal.py | 9 ++++++--- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/Android/testbed/app/src/main/python/main.py b/Android/testbed/app/src/main/python/main.py index c7314b500bf..d6941b14412 100644 --- a/Android/testbed/app/src/main/python/main.py +++ b/Android/testbed/app/src/main/python/main.py @@ -5,9 +5,25 @@ import signal import sys # Some tests use SIGUSR1, but that's blocked by default in an Android app in -# order to make it available to `sigwait` in the "Signal Catcher" thread. That -# thread's functionality is only relevant to the JVM ("forcing GC (no HPROF) and -# profile save"), so disabling it should not weaken the tests. +# order to make it available to `sigwait` in the Signal Catcher thread. +# (https://cs.android.com/android/platform/superproject/+/android14-qpr3-release:art/runtime/signal_catcher.cc). +# That thread's functionality is only useful for debugging the JVM, so disabling +# it should not weaken the tests. +# +# There's no safe way of stopping the thread completely (#123982), but simply +# unblocking SIGUSR1 is enough to fix most tests. +# +# However, in tests that generate multiple different signals in quick +# succession, it's possible for SIGUSR1 to arrive while the main thread is busy +# running the C-level handler for a different signal. In that case, the SIGUSR1 +# may be sent to the Signal Catcher thread instead, which will generate a log +# message containing the text "reacting to signal". +# +# Such tests may need to be changed in one of the following ways: +# * Use a signal other than SIGUSR1 (e.g. test_stress_delivery_simultaneous in +# test_signal.py). +# * Send the signal to a specific thread rather than the whole process (e.g. +# test_signals in test_threadsignals.py. signal.pthread_sigmask(signal.SIG_UNBLOCK, [signal.SIGUSR1]) sys.argv[1:] = shlex.split(os.environ["PYTHON_ARGS"]) diff --git a/Lib/test/test_signal.py b/Lib/test/test_signal.py index 7f8fe34bb31..da36b8576be 100644 --- a/Lib/test/test_signal.py +++ b/Lib/test/test_signal.py @@ -1325,15 +1325,18 @@ class StressTest(unittest.TestCase): def handler(signum, frame): sigs.append(signum) - self.setsig(signal.SIGUSR1, handler) + # On Android, SIGUSR1 is unreliable when used in close proximity to + # another signal – see Android/testbed/app/src/main/python/main.py. + # So we use a different signal. + self.setsig(signal.SIGUSR2, handler) self.setsig(signal.SIGALRM, handler) # for ITIMER_REAL expected_sigs = 0 while expected_sigs < N: # Hopefully the SIGALRM will be received somewhere during - # initial processing of SIGUSR1. + # initial processing of SIGUSR2. signal.setitimer(signal.ITIMER_REAL, 1e-6 + random.random() * 1e-5) - os.kill(os.getpid(), signal.SIGUSR1) + os.kill(os.getpid(), signal.SIGUSR2) expected_sigs += 2 # Wait for handlers to run to avoid signal coalescing