bpo-31629: Add support.SaveSignals (#4183) (#4187) · python/cpython@41efc40

2 files changed

lines changed

Original file line numberDiff line numberDiff line change

@@ -2621,3 +2621,42 @@ def disable_faulthandler():

26212621

finally:

26222622

if is_enabled:

26232623

faulthandler.enable(file=fd, all_threads=True)

2624+
2625+
2626+

class SaveSignals:

2627+

"""

2628+

Save an restore signal handlers.

2629+
2630+

This class is only able to save/restore signal handlers registered

2631+

by the Python signal module: see bpo-13285 for "external" signal

2632+

handlers.

2633+

"""

2634+
2635+

def __init__(self):

2636+

import signal

2637+

self.signal = signal

2638+

self.signals = list(range(1, signal.NSIG))

2639+

# SIGKILL and SIGSTOP signals cannot be ignored nor catched

2640+

for signame in ('SIGKILL', 'SIGSTOP'):

2641+

try:

2642+

signum = getattr(signal, signame)

2643+

except AttributeError:

2644+

continue

2645+

self.signals.remove(signum)

2646+

self.handlers = {}

2647+
2648+

def save(self):

2649+

for signum in self.signals:

2650+

handler = self.signal.getsignal(signum)

2651+

if handler is None:

2652+

# getsignal() returns None if a signal handler was not

2653+

# registered by the Python signal module,

2654+

# and the handler is not SIG_DFL nor SIG_IGN.

2655+

#

2656+

# Ignore the signal: we cannot restore the handler.

2657+

continue

2658+

self.handlers[signum] = handler

2659+
2660+

def restore(self):

2661+

for signum, handler in self.handlers.items():

2662+

self.signal.signal(signum, handler)

Original file line numberDiff line numberDiff line change

@@ -15,7 +15,7 @@

1515

import tempfile

1616

import unittest

1717
18-

from test.support import requires, import_module, verbose

18+

from test.support import requires, import_module, verbose, SaveSignals

1919
2020

# Optionally test curses module. This currently requires that the

2121

# 'curses' resource be given on the regrtest command line using the -u

@@ -63,6 +63,8 @@ def tearDownClass(cls):

6363

del cls.tmp

6464
6565

def setUp(self):

66+

self.save_signals = SaveSignals()

67+

self.save_signals.save()

6668

if verbose:

6769

# just to make the test output a little more readable

6870

print()

@@ -72,6 +74,7 @@ def setUp(self):

7274

def tearDown(self):

7375

curses.resetty()

7476

curses.endwin()

77+

self.save_signals.restore()

7578
7679

def test_window_funcs(self):

7780

"Test the methods of windows"