Last active
September 13, 2015 16:19
-
-
Save sophacles/996f1b18a5ac4263c5b5 to your computer and use it in GitHub Desktop.
a posix forkpty implementation for gevent - works with pexpect nicely
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Make a forkpty wrapper that works nicely with gevent. | |
# This only wraps the process properly, the same way gevent.os.fork() does, | |
# and doesn't do anything special for dealing with the pty file descriptor. | |
# | |
# This was originally intended to work with pexpect, and does so nicely, since the | |
# head version of pexpect uses select.select and time.sleep in many places, effectively | |
# "geventifying" the expect interactions. | |
# | |
# Other things using forkpty and doing reads and writes via the pty will need to | |
# take a look at doing proper gevent wrapping of operations on the fd for now. | |
# | |
# N.B. - This almost certainly does not work on windows. If it does, your code is | |
# probably wrong, and the accident of it working is not to be counted on even | |
# across boots on the same machine | |
import gevent | |
import os | |
import gevent.os | |
from gevent import monkey | |
_real_forkpty = os.forkpty | |
def forkpty_and_watch(callback=None, loop=None, ref=False, fork=None): | |
""" | |
This is the same as gevent.forkpty_and_watch, except it wraps | |
os.forkpty rather than os.fork. | |
""" | |
# note result is a pair of (pid, fd) | |
# the value of pid is the same as if fork ahd been called | |
# fd is the appropriate pty device fd (master or slave as needed by parent or child) | |
result = _real_forkpty() | |
# act like gevent_fork was called | |
if not result[0]: | |
gevent.reinit() | |
return result | |
pid = result[0] | |
# direct copy of fork_and_watch, transliterated for not being deep in gevent | |
if pid: | |
# parent | |
loop = gevent.get_hub().loop | |
watcher = loop.child(pid) | |
gevent.os._watched_children[pid] = watcher | |
watcher.start(gevent.os._on_child, watcher, callback) | |
# return value is the (pid, fd) pair as forkpty() returns | |
return result | |
# just patch forkpty as if gevent.monkey.patch_os or patch_all had done it | |
monkey.patch_item(os, 'forkpty', forkpty_and_watch) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment