this wait should be interrupted by excclass if set install handlers this function runs in a subprocess so we don t worry about resetting the default handlers let the subprocesses know who to send signals to gh110033 make sure that the subprocess popen is deleted before the next test which raises an exception otherwise the exception may be raised when popen del is executed and so be logged as exception ignored in function popen del at nothing should happen sigusr2 is ignored this wait should be interrupted by exc_class if set install handlers this function runs in a sub process so we don t worry about re setting the default handlers let the sub processes know who to send signals to gh 110033 make sure that the subprocess popen is deleted before the next test which raises an exception otherwise the exception may be raised when popen __del__ is executed and so be logged as exception ignored in function popen __del__ at nothing should happen sigusr2 is ignored
import gc
import os
import signal
import subprocess
import sys
import time
import unittest
from test import support


class SIGUSR1Exception(Exception):
    pass


class InterProcessSignalTests(unittest.TestCase):
    def setUp(self):
        self.got_signals = {'SIGHUP': 0, 'SIGUSR1': 0, 'SIGALRM': 0}

    def sighup_handler(self, signum, frame):
        self.got_signals['SIGHUP'] += 1

    def sigusr1_handler(self, signum, frame):
        self.got_signals['SIGUSR1'] += 1
        raise SIGUSR1Exception

    def wait_signal(self, child, signame):
        if child is not None:
            
            
            child.wait()

        start_time = time.monotonic()
        for _ in support.busy_retry(support.SHORT_TIMEOUT, error=False):
            if self.got_signals[signame]:
                return
            signal.pause()
        else:
            dt = time.monotonic() - start_time
            self.fail('signal %s not received after %.1f seconds'
                      % (signame, dt))

    def subprocess_send_signal(self, pid, signame):
        code = 'import os, signal; os.kill(%s, signal.%s)' % (pid, signame)
        args = [sys.executable, '-I', '-c', code]
        return subprocess.Popen(args)

    def test_interprocess_signal(self):
        
        
        signal.signal(signal.SIGHUP, self.sighup_handler)
        signal.signal(signal.SIGUSR1, self.sigusr1_handler)
        signal.signal(signal.SIGUSR2, signal.SIG_IGN)
        signal.signal(signal.SIGALRM, signal.default_int_handler)

        
        pid = str(os.getpid())

        with self.subprocess_send_signal(pid, "SIGHUP") as child:
            self.wait_signal(child, 'SIGHUP')
        self.assertEqual(self.got_signals, {'SIGHUP': 1, 'SIGUSR1': 0,
                                            'SIGALRM': 0})

        
        
        
        
        child = None
        gc.collect()

        with self.assertRaises(SIGUSR1Exception):
            with self.subprocess_send_signal(pid, "SIGUSR1") as child:
                self.wait_signal(child, 'SIGUSR1')
        self.assertEqual(self.got_signals, {'SIGHUP': 1, 'SIGUSR1': 1,
                                            'SIGALRM': 0})

        with self.subprocess_send_signal(pid, "SIGUSR2") as child:
            
            child.wait()

        try:
            with self.assertRaises(KeyboardInterrupt):
                signal.alarm(1)
                self.wait_signal(None, 'SIGALRM')
            self.assertEqual(self.got_signals, {'SIGHUP': 1, 'SIGUSR1': 1,
                                                'SIGALRM': 0})
        finally:
            signal.alarm(0)


if __name__ == "__main__":
    unittest.main()