classification
Title: curses.wrapper does not restore terminal if curses.getkey() gets KeyboardInterrupt
Type: behavior Stage: resolved
Components: Library (Lib) Versions: Python 3.4, Python 3.2, Python 3.3, Python 2.7
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: haypo, july, marcadam, python-dev, r.david.murray
Priority: normal Keywords: patch

Created on 2010-05-31 18:23 by july, last changed 2013-03-19 23:33 by haypo. This issue is now closed.

Files
File name Uploaded Description Edit
curses-getkey.patch july, 2010-06-03 13:29 apply to trunk
Messages (6)
msg106799 - (view) Author: July Tikhonov (july) * Date: 2010-05-31 18:23
Run test.py (below) in terminal, and interrupt it with Ctrl-C.

Result: terminal settings are not restored (checked with linux console and xterm, with Python 2.7 and 3.2).

# test.py
# Broke it with KeyboardInterrupt
import curses
def main(screen):
    k = screen.getkey()
curses.wrapper(main)
# Results are hardly readable due to the broken terminal.
# Something about KeyboardInterrupt

However, if getkey() is surrounded by try-except, behavior changes:

# test2.py
# Broke it with KeyboardInterrupt
import curses
def main2(screen):
    try:
        k = screen.getkey()
    except KeyboardInterrupt:
        raise
curses.wrapper(main2)
# Terminal is restored to its normal state.

In python3.2 test2.py results in traceback:

Traceback (most recent call last):
  File "test2.py", line 4, in main2
    k = screen.getkey()
_curses.error: no input

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "test2.py", line 7, in <module>
    curses.wrapper(main2)
  File "/usr/local/lib/python3.2/curses/wrapper.py", line 44, in wrapper
    return func(stdscr, *args, **kwds)
  File "test2.py", line 4, in main2
    k = screen.getkey()
KeyboardInterrupt


In 2.7 it results only in the latest part of traceback:

Traceback (most recent call last):
  File "test2.py", line 7, in <module>
    curses.wrapper(main2)
  File "/usr/local/lib/python2.7/curses/wrapper.py", line 44, in wrapper
    return func(stdscr, *args, **kwds)
  File "test2.py", line 4, in main2
    k = screen.getkey()
KeyboardInterrupt


The problem is that instead of a single KeyboardInterrupt, two exceptions are raised: KeyboardInterrupt and _curses.error('no input').

Possible solution is to suppress _curses.error in this case (since it is less relevant than KeyboardInterrupt, IMO).
msg106949 - (view) Author: July Tikhonov (july) * Date: 2010-06-03 13:29
Patch added.

Calls PyErr_CheckSignals(). If nothing happens, raises _curses.error.
msg184665 - (view) Author: Marc Adam Anderson (marcadam) * Date: 2013-03-19 19:21
Tested patch using Python 3.4.0a0 on Mac OS X 10.8.3 (12D78). Patch appears to fix the bug.
msg184669 - (view) Author: Roundup Robot (python-dev) Date: 2013-03-19 20:27
New changeset 8a08607abf32 by R David Murray in branch '3.2':
#8862: Fix curses cleanup with getchar is interrupted by a signal.
http://hg.python.org/cpython/rev/8a08607abf32

New changeset 342ef2ed8d05 by R David Murray in branch '3.3':
Merge: #8862: Fix curses cleanup with getchar is interrupted by a signal.
http://hg.python.org/cpython/rev/342ef2ed8d05

New changeset 4b9705fe3b2a by R David Murray in branch 'default':
Merge: #8862: Fix curses cleanup with getchar is interrupted by a signal.
http://hg.python.org/cpython/rev/4b9705fe3b2a

New changeset 58980d0084cc by R David Murray in branch '2.7':
#8862: Fix curses cleanup with getchar is interrupted by a signal.
http://hg.python.org/cpython/rev/58980d0084cc
msg184672 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2013-03-19 20:29
Committed.  We couldn't think of a way to write a test, so I committed it without one.

Thanks July and Marc.
msg184704 - (view) Author: STINNER Victor (haypo) * (Python committer) Date: 2013-03-19 23:33
See also #17209.
History
Date User Action Args
2013-03-19 23:33:10hayposetmessages: + msg184704
2013-03-19 20:29:18r.david.murraysetstatus: open -> closed

versions: + Python 3.3, Python 3.4
nosy: + r.david.murray

messages: + msg184672
resolution: fixed
stage: resolved
2013-03-19 20:28:00python-devsetnosy: + python-dev
messages: + msg184669
2013-03-19 19:26:36ned.deilysetnosy: + haypo
2013-03-19 19:21:46marcadamsetnosy: + marcadam
messages: + msg184665
2010-06-03 13:29:34julysetfiles: + curses-getkey.patch
keywords: + patch
messages: + msg106949
2010-05-31 18:23:57julycreate