bpo-31629: Add support.SaveSignals (#4183) (#4187)

test_curses now saves/restores signals. On FreeBSD, the curses module
sets handlers of some signals, but don't restore old handlers when
the module is deinitialized.

(cherry picked from commit 19f68301a1)
This commit is contained in:
Victor Stinner 2017-10-31 03:45:01 -07:00 committed by GitHub
parent 690c36f2f1
commit 41efc402f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 43 additions and 1 deletions

View File

@ -2621,3 +2621,42 @@ def disable_faulthandler():
finally:
if is_enabled:
faulthandler.enable(file=fd, all_threads=True)
class SaveSignals:
"""
Save an restore signal handlers.
This class is only able to save/restore signal handlers registered
by the Python signal module: see bpo-13285 for "external" signal
handlers.
"""
def __init__(self):
import signal
self.signal = signal
self.signals = list(range(1, signal.NSIG))
# SIGKILL and SIGSTOP signals cannot be ignored nor catched
for signame in ('SIGKILL', 'SIGSTOP'):
try:
signum = getattr(signal, signame)
except AttributeError:
continue
self.signals.remove(signum)
self.handlers = {}
def save(self):
for signum in self.signals:
handler = self.signal.getsignal(signum)
if handler is None:
# getsignal() returns None if a signal handler was not
# registered by the Python signal module,
# and the handler is not SIG_DFL nor SIG_IGN.
#
# Ignore the signal: we cannot restore the handler.
continue
self.handlers[signum] = handler
def restore(self):
for signum, handler in self.handlers.items():
self.signal.signal(signum, handler)

View File

@ -15,7 +15,7 @@ import sys
import tempfile
import unittest
from test.support import requires, import_module, verbose
from test.support import requires, import_module, verbose, SaveSignals
# Optionally test curses module. This currently requires that the
# 'curses' resource be given on the regrtest command line using the -u
@ -63,6 +63,8 @@ class TestCurses(unittest.TestCase):
del cls.tmp
def setUp(self):
self.save_signals = SaveSignals()
self.save_signals.save()
if verbose:
# just to make the test output a little more readable
print()
@ -72,6 +74,7 @@ class TestCurses(unittest.TestCase):
def tearDown(self):
curses.resetty()
curses.endwin()
self.save_signals.restore()
def test_window_funcs(self):
"Test the methods of windows"