]> granicus.if.org Git - python/commitdiff
#23792: Ignore KeyboardInterrupt when the pydoc pager is active.
authorR David Murray <rdmurray@bitdance.com>
Sun, 29 Mar 2015 19:15:40 +0000 (15:15 -0400)
committerR David Murray <rdmurray@bitdance.com>
Sun, 29 Mar 2015 19:15:40 +0000 (15:15 -0400)
Previously, if you hit ctl-c while the pager was active, the python that
launched the subprocess for the pager would see the KeyboardInterrupt in the
__exit__ method of the subprocess context manager where it was waiting for the
subprocess to complete, ending the wait.  This would leave the pager running,
while the interactive interpreter, after handling the exception by printing
it, would go back to trying to post a prompt...but the pager would generally
have the terminal in raw mode, and in any case would be still trying to read
from stdin.  On some systems, even exiting python at that point would not
restore the terminal mode.  The problem with raw mode could also happen if
ctl-C was hit when pydoc was called from the shell command line and the pager
was active.

Instead, we now wait on the subprocess in a loop, ignoring KeyboardInterrupt
just like the pager does, until the pager actually exits.

(Note: this was a regression relative to python2...in python2 the pager
is called via system, and system does not return until the pager exits.)

Lib/pydoc.py
Misc/NEWS

index 8bbebc9be3af9c8e239c1ac33a3fbb4ca3ed11cf..cf9e0f021ce9a439f55019556401f580d7771c8f 100755 (executable)
@@ -1452,11 +1452,18 @@ def pipepager(text, cmd):
     import subprocess
     proc = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE)
     try:
-        with proc:
-            with io.TextIOWrapper(proc.stdin, errors='backslashreplace') as pipe:
-                pipe.write(text)
+        with io.TextIOWrapper(proc.stdin, errors='backslashreplace') as pipe:
+            pipe.write(text)
     except OSError:
         pass # Ignore broken pipes caused by quitting the pager program.
+    while True:
+        try:
+            proc.wait()
+            break
+        except KeyboardInterrupt:
+            # Ignore ctl-c like the pager itself does.  Otherwise the pager is
+            # left running and the terminal is in raw mode and unusable.
+            pass
 
 def tempfilepager(text, cmd):
     """Page through text by invoking a program on a temporary file."""
index c6b5e1ccbffe9ab62e7249a5b8ede18c50a04932..9852102f90373d64ec738f9b142c49dc09e8c77d 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -21,6 +21,10 @@ Core and Builtins
 Library
 -------
 
+- Issue #23792: Ignore KeyboardInterrupt when the pydoc pager is active.
+  This mimics the behavior of the standard unix pagers, and prevents
+  pipepager from shutting down while the pager itself is still running.
+
 - Issue #23742: ntpath.expandvars() no longer loses unbalanced single quotes.
 
 - Issue #21802: The reader in BufferedRWPair now is closed even when closing