From 10e54aeaa234f2806b367c66e3fb4ac6568b39f6 Mon Sep 17 00:00:00 2001 From: Xavier de Gaye Date: Wed, 12 Oct 2016 20:13:24 +0200 Subject: [PATCH] Issue #20766: Fix references leaked by pdb in the handling of SIGINT handlers. --- Lib/pdb.py | 10 +++++++--- Lib/test/test_pdb.py | 23 +++++++++++++++++++++++ Misc/NEWS | 3 +++ 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/Lib/pdb.py b/Lib/pdb.py index b11ac0abd16..47972655f96 100755 --- a/Lib/pdb.py +++ b/Lib/pdb.py @@ -134,6 +134,8 @@ line_prefix = '\n-> ' # Probably a better default class Pdb(bdb.Bdb, cmd.Cmd): + _previous_sigint_handler = None + def __init__(self, completekey='tab', stdin=None, stdout=None, skip=None, nosigint=False): bdb.Bdb.__init__(self, skip=skip) @@ -187,8 +189,6 @@ class Pdb(bdb.Bdb, cmd.Cmd): self.message("\nProgram interrupted. (Use 'cont' to resume).") self.set_step() self.set_trace(frame) - # restore previous signal handler - signal.signal(signal.SIGINT, self._previous_sigint_handler) def reset(self): bdb.Bdb.reset(self) @@ -337,6 +337,10 @@ class Pdb(bdb.Bdb, cmd.Cmd): (expr, newvalue, oldvalue)) def interaction(self, frame, traceback): + # Restore the previous signal handler at the Pdb prompt. + if Pdb._previous_sigint_handler: + signal.signal(signal.SIGINT, Pdb._previous_sigint_handler) + Pdb._previous_sigint_handler = None if self.setup(frame, traceback): # no interaction desired at this time (happens if .pdbrc contains # a command like "continue") @@ -1037,7 +1041,7 @@ class Pdb(bdb.Bdb, cmd.Cmd): """ if not self.nosigint: try: - self._previous_sigint_handler = \ + Pdb._previous_sigint_handler = \ signal.signal(signal.SIGINT, self.sigint_handler) except ValueError: # ValueError happens when do_continue() is invoked from diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index 45ba5a96853..66a7b5573c0 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -911,6 +911,29 @@ def test_pdb_next_command_subiterator(): (Pdb) continue """ +def test_pdb_issue_20766(): + """Test for reference leaks when the SIGINT handler is set. + + >>> def test_function(): + ... i = 1 + ... while i <= 2: + ... sess = pdb.Pdb() + ... sess.set_trace(sys._getframe()) + ... print('pdb %d: %s' % (i, sess._previous_sigint_handler)) + ... i += 1 + + >>> with PdbTestInput(['continue', + ... 'continue']): + ... test_function() + > (6)test_function() + -> print('pdb %d: %s' % (i, sess._previous_sigint_handler)) + (Pdb) continue + pdb 1: + > (5)test_function() + -> sess.set_trace(sys._getframe()) + (Pdb) continue + pdb 2: + """ class PdbTestCase(unittest.TestCase): diff --git a/Misc/NEWS b/Misc/NEWS index 44e63d42f2d..28a7d944efb 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -107,6 +107,9 @@ Core and Builtins Library ------- +- Issue #20766: Fix references leaked by pdb in the handling of SIGINT + handlers. + - Issue #26293: Fixed writing ZIP files that starts not from the start of the file. Offsets in ZIP file now are relative to the start of the archive in conforming to the specification.