pty difficulties

Discussion in 'Python' started by Justin Dubs, Jan 24, 2004.

  1. Justin Dubs

    Justin Dubs Guest

    I'm writing a utility that runs a program inside of a pseudo-tty and
    then multiplexes both stdin and a fifo to the child's pty via a select
    loop.

    In other words, you run my program, tell it the name of the program to
    run and the name of the fifo to use and then you can interact with the
    program as per usual. However, you can also send data into the fifo
    and the program will see it as input just as if you'd typed it on the
    keyboard.

    As a test I'm running sbcl (a lisp interpreter) through my python
    program. It works like a charm in normal usage. However, if I dump
    more than 2K or so of code into the FIFO, sbcl gets the first K fine,
    but then seems to miss a chunk, get another character or two and then
    freeze. After that I am unable to interact with it via either stdin
    or the fifo even though the select loop is still running. The pty
    just seems to be dead, eating input and giving nothing back. So, I
    tried running a different Lisp interpreter (openmcl) instead, but the
    problem persisted. So, I just ran vim through it and it handled the
    2K of text just fine.

    However, vim is just sending the text into a buffer where-as sbcl is
    parsing and compiling it. If I add a sleep(1.0) after data is sent
    from the fifo to the pty then the problem goes away. So, it seems
    like if the child process can't pull things out of it's stdin as fast
    as I'm putting it in, something goes awry.

    Has anyone seen similar behavior? Does anyone have any idea why this
    would be happening?

    Any help would be greatly appreciated. Thanks everyone. The code is
    below.

    Justin Dubs


    Here's the code:

    from time import sleep
    from pty import spawn, fork
    from sys import stdin, stdout, stderr, exit, argv
    from os import fdopen, open, read, write, O_RDONLY, O_NONBLOCK
    from select import select
    from termios import tcgetattr, tcsetattr, tcdrain, ECHO, TCSADRAIN
    from tty import setraw

    if (len(argv) != 3):
    print "usage: vee.py program pipe"
    exit(0)

    pid, childID = fork()

    if pid == 0:
    spawn(argv[1])
    else:
    fifo = fdopen(open(argv[2], O_RDONLY | O_NONBLOCK), 'r')
    child = fdopen(childID, 'r+')

    attribs = tcgetattr(stdin)
    attribs[3] = attribs[3] & ~ECHO
    tcsetattr(stdin, TCSADRAIN, attribs)

    setraw(stdin)

    connections = { child : stdout, stdin : child, fifo : child }

    try:
    while True:
    readable = select(connections.keys(), [], [])[0]
    for f in readable:
    data = read(f.fileno(), 1024)
    connections[f].write(data)
    connections[f].flush()
    except (OSError, IOError):
    exit(0)
     
    Justin Dubs, Jan 24, 2004
    #1
    1. Advertising

  2. > while True:
    > readable = select(connections.keys(), [], [])[0]
    > for f in readable:
    > data = read(f.fileno(), 1024)
    > connections[f].write(data)
    > connections[f].flush()


    I believe your problem exists in the write and flush. All you seem to
    be doing is checking to see if your reading file handles are capable of
    reading, you never check to see if you can write to anything. Your lisp
    interpreter showcases the fact that it is not ready to get a write while
    it is interpreting, by failing. I believe the following should fix you up:

    while True:
    readable = select(connections.keys(), [], [])[0]
    for f in readable:
    if select([], [connections[f]], [], 0)[1]:
    data = read(f.fileno(), 1024)
    connections[f].write(data)
    connections[f].flush()

    - Josiah
     
    Josiah Carlson, Jan 24, 2004
    #2
    1. Advertising

  3. Justin Dubs

    Justin Dubs Guest

    Josiah Carlson <> wrote in message news:<butccm$2un$>...
    > > while True:
    > > readable = select(connections.keys(), [], [])[0]
    > > for f in readable:
    > > data = read(f.fileno(), 1024)
    > > connections[f].write(data)
    > > connections[f].flush()

    >
    > I believe your problem exists in the write and flush. All you seem to
    > be doing is checking to see if your reading file handles are capable of
    > reading, you never check to see if you can write to anything. Your lisp
    > interpreter showcases the fact that it is not ready to get a write while
    > it is interpreting, by failing. I believe the following should fix you up:
    >
    > while True:
    > readable = select(connections.keys(), [], [])[0]
    > for f in readable:
    > if select([], [connections[f]], [], 0)[1]:
    > data = read(f.fileno(), 1024)
    > connections[f].write(data)
    > connections[f].flush()


    Thanks for the suggestions, but this didn't help. I should have
    mentioned that I had tried this before. Here's the code I had used:

    while True:
    readable, writeable, ignore = select(connections.keys(),
    connections.values(), [])
    for f in readable:
    if connections[f] in writeable:
    data = read(f.fileno(), 1024)
    connections[f].write(data)
    connections[f].flush()

    I don't think checking for writeable status /should/ help because the
    write call I am using blocks. So, if the stream isn't writeable, it
    should just block until it is. I think.

    Justin Dubs
     
    Justin Dubs, Jan 24, 2004
    #3
  4. > I don't think checking for writeable status /should/ help because the
    > write call I am using blocks. So, if the stream isn't writeable, it
    > should just block until it is. I think.


    Hrm. Perhaps you should just leave the sleep in there. One second
    seems a bit much, but maybe .01 or .001 seconds is sufficient. You
    could reasonably still get 100K-1M/second. One would hope that would be
    enough for most tasks.

    - Josiah
     
    Josiah Carlson, Jan 24, 2004
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Evan Driscoll
    Replies:
    0
    Views:
    230
    Evan Driscoll
    Oct 24, 2012
  2. Evan Driscoll
    Replies:
    0
    Views:
    183
    Evan Driscoll
    Oct 24, 2012
  3. Evan Driscoll
    Replies:
    0
    Views:
    210
    Evan Driscoll
    Oct 24, 2012
  4. David Hutto
    Replies:
    0
    Views:
    221
    David Hutto
    Oct 24, 2012
  5. David Hutto
    Replies:
    0
    Views:
    204
    David Hutto
    Oct 24, 2012
Loading...

Share This Page