An OSX user submitted a bug that CTRL+Y causes a python terminal application to be suspended, via dsusp causing SIGTSTP to be sent when the Python program tried to read on stdin. The code below to solves the problem: (context)
import sys
import termios
if sys.platform == 'darwin':
attrs = termios.tcgetattr(0)
VDSUSP = termios.VSUSP + 1
attrs[-1][VDSUSP] = 0
termios.tcsetattr(0, termios.TCSANOW, attrs)
os.uname()
or similar?termios.VDSUSP
doesn't exist, even on systems that have it. Is there a reason it's missing?stty dsusp undef
to my .bashrc long ago so haven't noticed it.To see this suspend behavior, run cat
and enter CTRL+Y Return on OSX or something else with this feature.
$ cat
^Y
[1]+ Stopped cat
$ fg
cat
cat: stdin: Resource temporarily unavailable
I am unable to check the actual behaviour for this as I do not have any computers with an operating system that would have the DSUSP
behaviour.
However while investigating the issue, I came across issue 7695 in Python bug tracker. It seems that the VDSUSP
is available in termios
only from 3.4 onwards.
Glibc documentation, that says
Macro: int
VDSUSP
This is the subscript for the
DSUSP
character in the special control character array.termios.c_cc[VDSUSP]
holds the character itself.The
DSUSP
(suspend) character is recognized only if the implementation supports job control (see Job Control). It sends aSIGTSTP
signal, like theSUSP
character, but not right away—only when the program tries to read it as input. Not all systems with job control support DSUSP; only BSD-compatible systems (including GNU/Hurd systems).
Thus I'd propose that you'd check the existence of VDSUSP
in termios
- it will be there from 3.4 onwards; and otherwise fall back to
if any(i in sys.platform for i in ['bsd', 'darwin']):
Which should match BSD and your OS X; the Hurd is a big question mark since I couldn't find out whether your fix would be correct at all there or not (I guess it would work similarly on all BSD versions).
Even easier would be to just do:
import subprocess
import time
from distutils.spawn import find_executable
def exec_cmd(*args):
p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, _ = p.communicate()
return stdout
if find_executable('stty'):
modesave = exec_cmd('stty', '-g').strip()
exec_cmd('stty', 'dsusp', 'undef')
print("disabled ctrl-y")
time.sleep(2)
print("enabled ctrl-y")
exec_cmd('stty', modesave)
time.sleep(2)
print("exiting")
At least this does not blow up my Linux, and the stty
command itself and -g
etc are POSIX standards.