Skip to content

Commit 3604b23

Browse files
authored
bpo-31479: Always reset the signal alarm in tests (GH-3588) (GH-7314)
* bpo-31479: Always reset the signal alarm in tests Use "try: ... finally: signal.signal(0)" pattern to make sure that tests don't "leak" a pending fatal signal alarm. * Move two more alarm() calls into the try block Fix also typo: replace signal.signal(0) with signal.alarm(0) * Move another signal.alarm() into the try block (cherry picked from commit 9abee72)
1 parent 0f64262 commit 3604b23

File tree

7 files changed

+42
-24
lines changed

7 files changed

+42
-24
lines changed

Lib/test/test_io.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3146,18 +3146,20 @@ def _read():
31463146
try:
31473147
wio = self.io.open(w, **fdopen_kwargs)
31483148
t.start()
3149-
signal.alarm(1)
31503149
# Fill the pipe enough that the write will be blocking.
31513150
# It will be interrupted by the timer armed above. Since the
31523151
# other thread has read one byte, the low-level write will
31533152
# return with a successful (partial) result rather than an EINTR.
31543153
# The buffered IO layer must check for pending signal
31553154
# handlers, which in this case will invoke alarm_interrupt().
31563155
try:
3156+
signal.alarm(1)
31573157
with self.assertRaises(ZeroDivisionError):
31583158
wio.write(item * (support.PIPE_MAX_SIZE // len(item) + 1))
31593159
finally:
3160+
signal.alarm(0)
31603161
t.join()
3162+
31613163
# We got one byte, get another one and check that it isn't a
31623164
# repeat of the first one.
31633165
read_results.append(os.read(r, 1))
@@ -3206,6 +3208,7 @@ def on_alarm(*args):
32063208
if isinstance(exc, RuntimeError):
32073209
self.assertTrue(str(exc).startswith("reentrant call"), str(exc))
32083210
finally:
3211+
signal.alarm(0)
32093212
wio.close()
32103213
os.close(r)
32113214

@@ -3234,6 +3237,7 @@ def alarm_handler(sig, frame):
32343237
# - third raw read() returns b"bar"
32353238
self.assertEqual(decode(rio.read(6)), "foobar")
32363239
finally:
3240+
signal.alarm(0)
32373241
rio.close()
32383242
os.close(w)
32393243
os.close(r)
@@ -3295,6 +3299,7 @@ def alarm2(sig, frame):
32953299
self.assertIsNone(error[0])
32963300
self.assertEqual(N, sum(len(x) for x in read_results))
32973301
finally:
3302+
signal.alarm(0)
32983303
write_finished = True
32993304
os.close(w)
33003305
os.close(r)

Lib/test/test_pty.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,11 @@ class PtyTest(unittest.TestCase):
7070
def setUp(self):
7171
# isatty() and close() can hang on some platforms. Set an alarm
7272
# before running the test to make sure we don't hang forever.
73-
self.old_alarm = signal.signal(signal.SIGALRM, self.handle_sig)
73+
old_alarm = signal.signal(signal.SIGALRM, self.handle_sig)
74+
self.addCleanup(signal.signal, signal.SIGALRM, old_alarm)
75+
self.addCleanup(signal.alarm, 0)
7476
signal.alarm(10)
7577

76-
def tearDown(self):
77-
# remove alarm, restore old alarm handler
78-
signal.alarm(0)
79-
signal.signal(signal.SIGALRM, self.old_alarm)
80-
8178
def handle_sig(self, sig, frame):
8279
self.fail("isatty hung")
8380

Lib/test/test_signal.py

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,8 @@ def run_test(self):
138138
else:
139139
self.fail("pause returned of its own accord, and the signal"
140140
" didn't arrive after another second.")
141+
finally:
142+
signal.alarm(0)
141143

142144
# Issue 3864. Unknown if this affects earlier versions of freebsd also.
143145
@unittest.skipIf(sys.platform=='freebsd6',
@@ -246,11 +248,15 @@ def test_wakeup_fd_early(self):
246248
import select
247249

248250
signal.alarm(1)
249-
before_time = time.time()
250-
# We attempt to get a signal during the sleep,
251-
# before select is called
252-
time.sleep(self.TIMEOUT_FULL)
253-
mid_time = time.time()
251+
try:
252+
before_time = time.time()
253+
# We attempt to get a signal during the sleep,
254+
# before select is called
255+
time.sleep(self.TIMEOUT_FULL)
256+
mid_time = time.time()
257+
finally:
258+
signal.alarm(0)
259+
254260
self.assertTrue(mid_time - before_time < self.TIMEOUT_HALF)
255261
select.select([self.read], [], [], self.TIMEOUT_FULL)
256262
after_time = time.time()
@@ -260,11 +266,15 @@ def test_wakeup_fd_during(self):
260266
import select
261267

262268
signal.alarm(1)
263-
before_time = time.time()
264-
# We attempt to get a signal during the select call
265-
self.assertRaises(select.error, select.select,
266-
[self.read], [], [], self.TIMEOUT_FULL)
267-
after_time = time.time()
269+
try:
270+
before_time = time.time()
271+
# We attempt to get a signal during the select call
272+
self.assertRaises(select.error, select.select,
273+
[self.read], [], [], self.TIMEOUT_FULL)
274+
after_time = time.time()
275+
finally:
276+
signal.alarm(0)
277+
268278
self.assertTrue(after_time - before_time < self.TIMEOUT_HALF)
269279

270280
def setUp(self):

Lib/test/test_socket.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1534,8 +1534,8 @@ def alarm_handler(signal, frame):
15341534
raise Alarm
15351535
old_alarm = signal.signal(signal.SIGALRM, alarm_handler)
15361536
try:
1537-
signal.alarm(2) # POSIX allows alarm to be up to 1 second early
15381537
try:
1538+
signal.alarm(2) # POSIX allows alarm to be up to 1 second early
15391539
foo = self.serv.accept()
15401540
except socket.timeout:
15411541
self.fail("caught timeout instead of Alarm")

Lib/test/test_socketserver.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,13 @@ class SocketServerTest(unittest.TestCase):
8888
"""Test all socket servers."""
8989

9090
def setUp(self):
91+
self.addCleanup(signal_alarm, 0)
9192
signal_alarm(60) # Kill deadlocks after 60 seconds.
9293
self.port_seed = 0
9394
self.test_files = []
9495

9596
def tearDown(self):
96-
signal_alarm(0) # Didn't deadlock.
97+
self.doCleanups()
9798
reap_children()
9899

99100
for fn in self.test_files:

Lib/test/test_subprocess.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -843,8 +843,11 @@ def handler(signum, frame):
843843
kw = {stream: subprocess.PIPE}
844844
with subprocess.Popen(args, **kw) as process:
845845
signal.alarm(1)
846-
# communicate() will be interrupted by SIGALRM
847-
process.communicate()
846+
try:
847+
# communicate() will be interrupted by SIGALRM
848+
process.communicate()
849+
finally:
850+
signal.alarm(0)
848851

849852

850853
@unittest.skipIf(mswindows, "POSIX specific tests")

Lib/test/test_threadsignals.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,11 @@ def test_signals(self):
5252
# wait for it return.
5353
if signal_blackboard[signal.SIGUSR1]['tripped'] == 0 \
5454
or signal_blackboard[signal.SIGUSR2]['tripped'] == 0:
55-
signal.alarm(1)
56-
signal.pause()
57-
signal.alarm(0)
55+
try:
56+
signal.alarm(1)
57+
signal.pause()
58+
finally:
59+
signal.alarm(0)
5860

5961
self.assertEqual( signal_blackboard[signal.SIGUSR1]['tripped'], 1)
6062
self.assertEqual( signal_blackboard[signal.SIGUSR1]['tripped_by'],

0 commit comments

Comments
 (0)