tahsmith
tahsmith

Reputation: 1723

Managing a subprocess with gevent and stdin

I have written a small program to start and stop a subprocess on command from read from stdin, using gevent to, hopefully, efficiently wait for both the command input, and for the process to finish.

It has one command R - run, which it read of stdin as a line.

R simply starts sh with the script sleep 2; echo "Hello, world!" if it is not already running

There are two greenlets, one reading command input and one waiting for a new process or waiting for the current process to finish. I use an gevent Event to toggle between the two.

My problem: The greenlet for the process is never allow to finish. The command greenlet appears to always be running and never relinquishes control. Why does the process greenlet never wake from its wait, even when the process is clearly finished?

The source is as follows:

import sys
from gevent import spawn, joinall, sleep
from gevent.subprocess import Popen
from gevent.fileobject import FileObjectPosix
from gevent.event import Event

process = None
trigger = Event()

def start_process():
    global process
    process = Popen(['/bin/sh', '-c', 'sleep 2; echo Hello, World!'])

def wait_process():
    global process
    while True:
        trigger.wait()
        print('INFO - Awaiting new process')
        trigger.clear()
        process.wait()
        process = None
        print('INFO - Process done')

def get_input():
    global process
    stdin_wrapped = FileObjectPosix(sys.stdin)
    while True:
        line = stdin_wrapped.readline().decode().strip()
        if line == 'R':
            if not process:
                start_process()
                trigger.set()
                print('OK - Running process')

            else:
                print('FAIL - Process already running')
        sleep(0)

def main():
    joinall([
        spawn(get_input),
        spawn(wait_process)
    ])

if __name__ == '__main__':
    main()

A session looks like this, with a >2s gap between the Rs:

R
OK - Running process
INFO - Awaiting new process
Hello, World!
R
FAIL - Process already running

I expect to see:

R
OK - Running process
INFO - Awaiting new process
Hello, World!
INFO - Process done
R
OK - Running process

My initial ideas are one of two things are going wrong:

Upvotes: 0

Views: 628

Answers (1)

tahsmith
tahsmith

Reputation: 1723

I have two solutions to my own problem. Either of these will make my example program function as expected.

Pipe for stdin

Open the subprocess with Popen(..., stdin=PIPE). It makes sense that gevent won't work without that since it must wait on something.

Use FileObjectThread

This seems to work regardless of how the subprocess is created, not sure why 😐

Upvotes: 0

Related Questions