@@ -371,64 +371,55 @@ def test_sleep(self):
371
371
372
372
373
373
@unittest .skipUnless (hasattr (signal , "setitimer" ), "requires setitimer()" )
374
+ # bpo-30320: Need pthread_sigmask() to block the signal, otherwise the test
375
+ # is vulnerable to a race condition between the child and the parent processes.
376
+ @unittest .skipUnless (hasattr (signal , 'pthread_sigmask' ),
377
+ 'need signal.pthread_sigmask()' )
374
378
class SignalEINTRTest (EINTRBaseTest ):
375
379
""" EINTR tests for the signal module. """
376
380
377
- @unittest .skipUnless (hasattr (signal , 'sigtimedwait' ),
378
- 'need signal.sigtimedwait()' )
379
- def test_sigtimedwait (self ):
380
- t0 = time .monotonic ()
381
- signal .sigtimedwait ([signal .SIGUSR1 ], self .sleep_time )
382
- dt = time .monotonic () - t0
383
-
384
- if sys .platform .startswith ('aix' ):
385
- # On AIX, sigtimedwait(0.2) sleeps 199.8 ms
386
- self .assertGreaterEqual (dt , self .sleep_time * 0.9 )
387
- else :
388
- self .assertGreaterEqual (dt , self .sleep_time )
389
-
390
- @unittest .skipUnless (hasattr (signal , 'sigwaitinfo' ),
391
- 'need signal.sigwaitinfo()' )
392
- def test_sigwaitinfo (self ):
393
- # Issue #25277, #25868: give a few milliseconds to the parent process
394
- # between os.write() and signal.sigwaitinfo() to works around a race
395
- # condition
396
- self .sleep_time = 0.100
397
-
381
+ def check_sigwait (self , wait_func ):
398
382
signum = signal .SIGUSR1
399
383
pid = os .getpid ()
400
384
401
385
old_handler = signal .signal (signum , lambda * args : None )
402
386
self .addCleanup (signal .signal , signum , old_handler )
403
387
404
- rpipe , wpipe = os .pipe ()
405
-
406
388
code = '\n ' .join ((
407
389
'import os, time' ,
408
390
'pid = %s' % os .getpid (),
409
391
'signum = %s' % int (signum ),
410
392
'sleep_time = %r' % self .sleep_time ,
411
- 'rpipe = %r' % rpipe ,
412
- 'os.read(rpipe, 1)' ,
413
- 'os.close(rpipe)' ,
414
393
'time.sleep(sleep_time)' ,
415
394
'os.kill(pid, signum)' ,
416
395
))
417
396
397
+ old_mask = signal .pthread_sigmask (signal .SIG_BLOCK , [signum ])
398
+ self .addCleanup (signal .pthread_sigmask , signal .SIG_UNBLOCK , [signum ])
399
+
418
400
t0 = time .monotonic ()
419
- proc = self .subprocess (code , pass_fds = (rpipe ,))
420
- os .close (rpipe )
401
+ proc = self .subprocess (code )
421
402
with kill_on_error (proc ):
422
- # sync child-parent
423
- os .write (wpipe , b'x' )
424
- os .close (wpipe )
403
+ wait_func (signum )
404
+ dt = time .monotonic () - t0
405
+
406
+ self .assertEqual (proc .wait (), 0 )
425
407
426
- # parent
408
+ @unittest .skipUnless (hasattr (signal , 'sigwaitinfo' ),
409
+ 'need signal.sigwaitinfo()' )
410
+ def test_sigwaitinfo (self ):
411
+ def wait_func (signum ):
427
412
signal .sigwaitinfo ([signum ])
428
- dt = time .monotonic () - t0
429
- self .assertEqual (proc .wait (), 0 )
430
413
431
- self .assertGreaterEqual (dt , self .sleep_time )
414
+ self .check_sigwait (wait_func )
415
+
416
+ @unittest .skipUnless (hasattr (signal , 'sigtimedwait' ),
417
+ 'need signal.sigwaitinfo()' )
418
+ def test_sigtimedwait (self ):
419
+ def wait_func (signum ):
420
+ signal .sigtimedwait ([signum ], 120.0 )
421
+
422
+ self .check_sigwait (wait_func )
432
423
433
424
434
425
@unittest .skipUnless (hasattr (signal , "setitimer" ), "requires setitimer()" )
0 commit comments