@@ -371,64 +371,55 @@ def test_sleep(self):
371371
372372
373373@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()' )
374378class SignalEINTRTest (EINTRBaseTest ):
375379 """ EINTR tests for the signal module. """
376380
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 ):
398382 signum = signal .SIGUSR1
399383 pid = os .getpid ()
400384
401385 old_handler = signal .signal (signum , lambda * args : None )
402386 self .addCleanup (signal .signal , signum , old_handler )
403387
404- rpipe , wpipe = os .pipe ()
405-
406388 code = '\n ' .join ((
407389 'import os, time' ,
408390 'pid = %s' % os .getpid (),
409391 'signum = %s' % int (signum ),
410392 'sleep_time = %r' % self .sleep_time ,
411- 'rpipe = %r' % rpipe ,
412- 'os.read(rpipe, 1)' ,
413- 'os.close(rpipe)' ,
414393 'time.sleep(sleep_time)' ,
415394 'os.kill(pid, signum)' ,
416395 ))
417396
397+ old_mask = signal .pthread_sigmask (signal .SIG_BLOCK , [signum ])
398+ self .addCleanup (signal .pthread_sigmask , signal .SIG_UNBLOCK , [signum ])
399+
418400 t0 = time .monotonic ()
419- proc = self .subprocess (code , pass_fds = (rpipe ,))
420- os .close (rpipe )
401+ proc = self .subprocess (code )
421402 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 )
425407
426- # parent
408+ @unittest .skipUnless (hasattr (signal , 'sigwaitinfo' ),
409+ 'need signal.sigwaitinfo()' )
410+ def test_sigwaitinfo (self ):
411+ def wait_func (signum ):
427412 signal .sigwaitinfo ([signum ])
428- dt = time .monotonic () - t0
429- self .assertEqual (proc .wait (), 0 )
430413
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 )
432423
433424
434425@unittest .skipUnless (hasattr (signal , "setitimer" ), "requires setitimer()" )
0 commit comments