Skip to content

Commit 2c6cf90

Browse files
gh-152548: Skip the test_signal pipe write test without a subprocess
Move the "OS doesn't report write() error on the read end of a pipe" check out of test_wakeup_write_error into a decorator placed above @runInSubprocess(), so that the test is skipped in the parent process instead of spawning a subprocess first. Replace the six identical no-op signal handlers of the wakeup tests with a global noop_handler(). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 37bc54a commit 2c6cf90

1 file changed

Lines changed: 38 additions & 34 deletions

File tree

Lib/test/test_signal.py

Lines changed: 38 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,36 @@
2424
_testcapi = None
2525

2626

27+
def noop_handler(signum, frame):
28+
pass
29+
30+
31+
def requires_write_error_on_pipe_read_end(func):
32+
"""Skip the test if writing to the read end of a pipe does not fail.
33+
34+
Check this only in the parent process, so that the test is skipped without
35+
first spawning a subprocess for it.
36+
"""
37+
if isolation.runningInSubprocess:
38+
return func
39+
40+
@functools.wraps(func)
41+
def wrapper(self, /, *args, **kwargs):
42+
r, w = os.pipe()
43+
try:
44+
os.write(r, b'x')
45+
except OSError:
46+
pass
47+
else:
48+
raise unittest.SkipTest(
49+
"OS doesn't report write() error on the read end of a pipe")
50+
finally:
51+
os.close(r)
52+
os.close(w)
53+
return func(self, *args, **kwargs)
54+
return wrapper
55+
56+
2757
class GenericTests(unittest.TestCase):
2858

2959
def test_enums(self):
@@ -320,10 +350,7 @@ def check_wakeup(self, test, *signals, ordered=True):
320350

321351
signals = tuple(int(s) for s in signals)
322352

323-
def handler(signum, frame):
324-
pass
325-
326-
signal.signal(signal.SIGALRM, handler)
353+
signal.signal(signal.SIGALRM, noop_handler)
327354
read, write = os.pipe()
328355
os.set_blocking(write, False)
329356
signal.set_wakeup_fd(write)
@@ -343,22 +370,12 @@ def handler(signum, frame):
343370
@unittest.skipIf(_testcapi is None, 'need _testcapi')
344371
@unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()")
345372
@force_not_colorized
373+
@requires_write_error_on_pipe_read_end
346374
@isolation.runInSubprocess()
347375
def test_wakeup_write_error(self):
348376
# Issue #16105: write() errors in the C signal handler should not
349377
# pass silently.
350378
# Use @runInSubprocess() to run in a subprocess with only one thread.
351-
r, w = os.pipe()
352-
try:
353-
os.write(r, b'x')
354-
except OSError:
355-
pass
356-
else:
357-
self.skipTest("OS doesn't report write() error on the read end of a pipe")
358-
finally:
359-
os.close(r)
360-
os.close(w)
361-
362379
def handler(signum, frame):
363380
1/0
364381

@@ -451,9 +468,7 @@ def handler(signum, frame):
451468
@isolation.runInSubprocess()
452469
def test_signum(self):
453470
def test(read):
454-
def handler(signum, frame):
455-
pass
456-
signal.signal(signal.SIGUSR1, handler)
471+
signal.signal(signal.SIGUSR1, noop_handler)
457472
signal.raise_signal(signal.SIGUSR1)
458473
signal.raise_signal(signal.SIGALRM)
459474
self.check_wakeup(test, signal.SIGUSR1, signal.SIGALRM)
@@ -467,10 +482,8 @@ def test(read):
467482
signum1 = signal.SIGUSR1
468483
signum2 = signal.SIGUSR2
469484

470-
def handler(signum, frame):
471-
pass
472-
signal.signal(signum1, handler)
473-
signal.signal(signum2, handler)
485+
signal.signal(signum1, noop_handler)
486+
signal.signal(signum2, noop_handler)
474487

475488
signal.pthread_sigmask(signal.SIG_BLOCK, (signum1, signum2))
476489
signal.raise_signal(signum1)
@@ -492,10 +505,7 @@ def test_socket(self):
492505
signum = signal.SIGINT
493506
signals = (signum,)
494507

495-
def handler(signum, frame):
496-
pass
497-
498-
signal.signal(signum, handler)
508+
signal.signal(signum, noop_handler)
499509

500510
read, write = socket.socketpair()
501511
write.setblocking(False)
@@ -522,10 +532,7 @@ def test_send_error(self):
522532

523533
signum = signal.SIGINT
524534

525-
def handler(signum, frame):
526-
pass
527-
528-
signal.signal(signum, handler)
535+
signal.signal(signum, noop_handler)
529536

530537
read, write = socket.socketpair()
531538
read.setblocking(False)
@@ -558,10 +565,7 @@ def test_warn_on_full_buffer(self):
558565

559566
# This handler will be called, but we intentionally won't read from
560567
# the wakeup fd.
561-
def handler(signum, frame):
562-
pass
563-
564-
signal.signal(signum, handler)
568+
signal.signal(signum, noop_handler)
565569

566570
read, write = socket.socketpair()
567571

0 commit comments

Comments
 (0)