|
7 | 7 | import os |
8 | 8 | import pdb |
9 | 9 | import re |
| 10 | +import signal |
10 | 11 | import sys |
11 | 12 | import types |
12 | 13 | import codecs |
@@ -2973,6 +2974,118 @@ def test_pdb_with_inline_breakpoint(): |
2973 | 2974 | (Pdb) c |
2974 | 2975 | """ |
2975 | 2976 |
|
| 2977 | +def test_pdb_sigint_continue(): |
| 2978 | + """SIGINT interrupts continue with a breakpoint set. |
| 2979 | +
|
| 2980 | + >>> def callee(): |
| 2981 | + ... signal.raise_signal(signal.SIGINT) |
| 2982 | + ... return 42 |
| 2983 | + >>> def caller(): |
| 2984 | + ... result = callee() |
| 2985 | + ... return result |
| 2986 | +
|
| 2987 | + With a breakpoint after the call, tracing remains active. The signal |
| 2988 | + stops in the callee, and continuing then reaches the breakpoint. |
| 2989 | +
|
| 2990 | + >>> with PdbTestInput(['break 3', 'continue', 'continue', 'continue']): |
| 2991 | + ... try: |
| 2992 | + ... pdb.Pdb(readrc=False).runcall(caller) |
| 2993 | + ... except KeyboardInterrupt: |
| 2994 | + ... raise AssertionError('SIGINT unwound the debuggee') |
| 2995 | + > <doctest test.test_pdb.test_pdb_sigint_continue[1]>(2)caller() |
| 2996 | + -> result = callee() |
| 2997 | + (Pdb) break 3 |
| 2998 | + Breakpoint 1 at <doctest test.test_pdb.test_pdb_sigint_continue[1]>:3 |
| 2999 | + (Pdb) continue |
| 3000 | + <BLANKLINE> |
| 3001 | + Program interrupted. (Use 'cont' to resume). |
| 3002 | + > <doctest test.test_pdb.test_pdb_sigint_continue[0]>(2)callee() |
| 3003 | + -> signal.raise_signal(signal.SIGINT) |
| 3004 | + (Pdb) continue |
| 3005 | + > <doctest test.test_pdb.test_pdb_sigint_continue[1]>(3)caller() |
| 3006 | + -> return result |
| 3007 | + (Pdb) continue |
| 3008 | + 42 |
| 3009 | + """ |
| 3010 | + |
| 3011 | + |
| 3012 | +def test_pdb_sigint_step(): |
| 3013 | + """SIGINT during step stops in the debuggee, not in Pdb's handler. |
| 3014 | +
|
| 3015 | + >>> def test_function(): |
| 3016 | + ... signal.raise_signal(signal.SIGINT) |
| 3017 | + ... return 42 |
| 3018 | +
|
| 3019 | + >>> with PdbTestInput(['step', 'continue']): |
| 3020 | + ... try: |
| 3021 | + ... pdb.Pdb(readrc=False).runcall(test_function) |
| 3022 | + ... except KeyboardInterrupt: |
| 3023 | + ... raise AssertionError('SIGINT unwound the debuggee') |
| 3024 | + > <doctest test.test_pdb.test_pdb_sigint_step[0]>(2)test_function() |
| 3025 | + -> signal.raise_signal(signal.SIGINT) |
| 3026 | + (Pdb) step |
| 3027 | + <BLANKLINE> |
| 3028 | + Program interrupted. (Use 'cont' to resume). |
| 3029 | + > <doctest test.test_pdb.test_pdb_sigint_step[0]>(2)test_function() |
| 3030 | + -> signal.raise_signal(signal.SIGINT) |
| 3031 | + (Pdb) continue |
| 3032 | + 42 |
| 3033 | + """ |
| 3034 | + |
| 3035 | + |
| 3036 | +def test_pdb_sigint_next(): |
| 3037 | + """SIGINT during next stops inside a previously untraced callee. |
| 3038 | +
|
| 3039 | + >>> def callee(): |
| 3040 | + ... signal.raise_signal(signal.SIGINT) |
| 3041 | + ... return 42 |
| 3042 | + >>> def caller(): |
| 3043 | + ... result = callee() |
| 3044 | + ... return result |
| 3045 | +
|
| 3046 | + >>> with PdbTestInput(['next', 'continue']): |
| 3047 | + ... try: |
| 3048 | + ... pdb.Pdb(readrc=False).runcall(caller) |
| 3049 | + ... except KeyboardInterrupt: |
| 3050 | + ... raise AssertionError('SIGINT unwound the debuggee') |
| 3051 | + > <doctest test.test_pdb.test_pdb_sigint_next[1]>(2)caller() |
| 3052 | + -> result = callee() |
| 3053 | + (Pdb) next |
| 3054 | + <BLANKLINE> |
| 3055 | + Program interrupted. (Use 'cont' to resume). |
| 3056 | + > <doctest test.test_pdb.test_pdb_sigint_next[0]>(2)callee() |
| 3057 | + -> signal.raise_signal(signal.SIGINT) |
| 3058 | + (Pdb) continue |
| 3059 | + 42 |
| 3060 | + """ |
| 3061 | + |
| 3062 | + |
| 3063 | +def test_pdb_sigint_until(): |
| 3064 | + """SIGINT during until stops inside a previously untraced callee. |
| 3065 | +
|
| 3066 | + >>> def callee(): |
| 3067 | + ... signal.raise_signal(signal.SIGINT) |
| 3068 | + ... return 42 |
| 3069 | + >>> def caller(): |
| 3070 | + ... result = callee() |
| 3071 | + ... return result |
| 3072 | +
|
| 3073 | + >>> with PdbTestInput(['until 3', 'continue']): |
| 3074 | + ... try: |
| 3075 | + ... pdb.Pdb(readrc=False).runcall(caller) |
| 3076 | + ... except KeyboardInterrupt: |
| 3077 | + ... raise AssertionError('SIGINT unwound the debuggee') |
| 3078 | + > <doctest test.test_pdb.test_pdb_sigint_until[1]>(2)caller() |
| 3079 | + -> result = callee() |
| 3080 | + (Pdb) until 3 |
| 3081 | + <BLANKLINE> |
| 3082 | + Program interrupted. (Use 'cont' to resume). |
| 3083 | + > <doctest test.test_pdb.test_pdb_sigint_until[0]>(2)callee() |
| 3084 | + -> signal.raise_signal(signal.SIGINT) |
| 3085 | + (Pdb) continue |
| 3086 | + 42 |
| 3087 | + """ |
| 3088 | + |
2976 | 3089 | def test_pdb_issue_20766(): |
2977 | 3090 | """Test for reference leaks when the SIGINT handler is set. |
2978 | 3091 |
|
@@ -5432,9 +5545,15 @@ def setUpPdbBackend(backend): |
5432 | 5545 | def setUp(test): |
5433 | 5546 | import pdb |
5434 | 5547 | pdb.set_default_backend(backend) |
| 5548 | + test.original_sigint_handler = signal.getsignal(signal.SIGINT) |
| 5549 | + test.previous_sigint_handler = pdb.Pdb._previous_sigint_handler |
5435 | 5550 | return setUp |
5436 | 5551 |
|
5437 | 5552 | def tearDown(test): |
| 5553 | + # Restore signal state even if a SIGINT doctest fails. |
| 5554 | + signal.signal(signal.SIGINT, test.original_sigint_handler) |
| 5555 | + pdb.Pdb._previous_sigint_handler = test.previous_sigint_handler |
| 5556 | + |
5438 | 5557 | # Ensure that asyncio state has been cleared at the end of the test. |
5439 | 5558 | # This prevents a "test altered the execution environment" warning if |
5440 | 5559 | # asyncio features are used. |
|
0 commit comments