Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Input fails after killing less(1) subprocess

I'm writing a program which displays text on the terminal using Unix less(1). Here is the relevant portion:

less = subprocess.Popen(['less -F -'], stdin=subprocess.PIPE, 
            stdout=sys.stdout, shell=True)
try:
    less.stdin.write(rfc_text)
    less.stdin.flush()
    less.stdin = sys.stdin
    less.wait()
except IOError:
    less.terminate()
    return errno.EPIPE
except KeyboardInterrupt:
    less.terminate()
    return 0

While waiting for less to finish, I listen for the KeyboardInterrupt exception. If I catch one, I kill less with a SIGTERM signal, and exit my program.

Now, when that happens, I'm returned to my shell prompt, but the shell no longer echoes what I write and I have to do a reset(1) to make it work again.

Any ideas on how to make less die without taking my stdin with it into the grave? The full source is available on https://github.com/jforberg/rfc/blob/master/rfc.py

EDIT: After some experimenting, I have found out that both less(1) and man(1) by default ignore the control-C stroke. So simply ignoring it may be a viable option. I'm not sure I think it's the proper way to do it though, so if someone has suggestions I'm still very much interested.

like image 896
jforberg Avatar asked Nov 05 '22 09:11

jforberg


1 Answers

The simplest way is to ask user to exit less properly (by pressing q):

#!/usr/bin/env python
from subprocess import PIPE, Popen

p = Popen(['less'], stdin=PIPE)
try:
    p.communicate(''.join("%d\n" % i for i in range(1000)))
except KeyboardInterrupt:
    print("Press `q` to exit.")
    p.wait()
like image 184
jfs Avatar answered Nov 09 '22 11:11

jfs