Reputation: 413
I need to terminate thread but can't check regularly any flags since it waits for reading/input.
Simple example:
import threading, time
class Test(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
print(input("wainting for input: "))
th = Test()
th.start()
time.sleep(5)
print("killing!")
th.join(5)
print(th.is_alive())
The more real example is this (kill thread when it hangs - no output for longer time):
import threading, time
class Test(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def call(args):
return subprocess.Popen(" ".join(args), shell=True, stderr=subprocess.PIPE)
def run(self):
mainProcess = call([ any program that could hang])
out = None
while mainProcess.returncode != 0 or out == '' and mainProcess.poll() != None:
out = mainProcess.stderr.read(1)
if out != '':
sys.stdout.write(out)
sys.stdout.flush()
th = Test()
th.start()
time.sleep(5)
print("killing!")
th.join(5)
print(th.is_alive())
If there is a better approach, I would be happy too.
Upvotes: 0
Views: 400
Reputation: 42768
Here's an example, how you can solve your hanging process problem with select
:
import threading
import select
import subprocess
import sys
def watch_output(args, timeout):
process = subprocess.Popen(args, stdout=subprocess.PIPE)
while True:
ready_to_read, _, _ = select.select([process.stdout], [], [], timeout)
if not ready_to_read:
print "hanging process"
process.kill()
break
out = ready_to_read[0].read(1)
if not out:
print "normal exit"
break
sys.stdout.write(out)
sys.stdout.flush()
return process.wait()
watch_output(['ls'], timeout=10)
or even your input with timeout is possible:
def read_input(prompt, timeout):
sys.stdout.write(prompt)
sys.stdout.flush()
ready_to_read, _, _ = select.select([sys.stdin], [], [], timeout)
if not ready_to_read:
return None
return ready_to_read[0].readline()
print read_input("wainting for input (4s): ", 4)
Upvotes: 1
Reputation: 52049
You can just have the main thread kill the process. The reader thread will eventually hit EOF and then exit.
Example:
#!/usr/bin/env python
import threading
import subprocess
import time
import sys
def pipe_thread(handle):
print "in pipe_thread"
x = handle.readline()
while x:
print "got:", x[:-1]
x = handle.readline()
def main():
p = subprocess.Popen(["./sender"], stdout = subprocess.PIPE)
t = threading.Thread(target = pipe_thread, args = [p.stdout])
t.start()
print "sleeping for a while"
time.sleep(5)
print "killing process"
p.kill()
print "joining"
t.join()
print "joined"
main()
Upvotes: 0