I am wondering how to check to see if a parent thread is still alive/stuck. Basically I have a parent thread sending commands to a child. If parent thread dies or hits a deadlock condition I do not want the child to continue to live. Below is basic framework of my implementation thus far.
from Queue import Queue
from threading import Thread
class myClass:
def __init__(self):
self.currentCommand = Queue()
t = Thread(target=self._run)
t.start()
def close(self):
self._sendCommand("close")
def _run(self):
while True:
if self.currentCommand.empty():
pass
#do some task
else:
command = self.currentCommand.get()
if command == "close":
#clean up
self.currentCommand.task_done()
break
else:
#do command task
self.currentCommand.task_done()
def _sendCommand(self, command):
self.currentCommand.put(command)
self.currentCommand.join()
One idea I have is to periodically send computer time to child from parent. If time is greater than a set value child will die. Is there a easier or more effect method? Also within the python documentation, there is an isAlive method within the threading class but I am unsure how to use it.
You could just pass an Event object down to the child thread, which it can check to see if the parent indicated a quit. Then you just wrap the critical section in the parent thread with a finally that will set the bit no matter what:
import time
from threading import Thread, Event
def child(quit):
for _ in xrange(10):
if quit.isSet():
print "Parent is dead. Leaving child."
return
print "Child alive"
time.sleep(.5)
def parent():
quitEvent = Event()
t = Thread(target=child, args=(quitEvent,))
t.start()
try:
time.sleep(2)
raise Exception("Parent thread raises exception")
finally:
quitEvent.set()
t.join()
if __name__ == "__main__":
t = Thread(target=parent, args=())
t.start()
t.join()
Though the matter of the parent thread dead-locking during it's own work would probably require a "heartbeat" approach like you suggested, where it is periodically indicating that it is alive. You could do that with either the queue that you pass down to the child, or you can continue to use the Event object. The parent would periodically set the event, and the child would expect it to be set at certain intervals, and then would clear it right after.
Here is an example of using the Event as a heartbeat, in the case where the parent might be deadlocked and not checking in:
def child(heartbeat):
for _ in xrange(10):
if not heartbeat.isSet():
print "Parent is dead. Leaving child."
return
heartbeat.clear()
print "Child alive"
time.sleep(1)
def parent():
heartbeat = Event()
heartbeat.set()
t = Thread(target=child, args=(heartbeat,))
t.start()
i = 0
while i < 20:
print "Parent alive"
i += 1
heartbeat.set()
time.sleep(.1)
print "Parent done looping...pretending to be deadlocked"
time.sleep(5)
t.join()
As the parent is doing it's own work, it is setting the heartbeat bit. The child is checking for this bit periodically. If it finds the parent is not set, then it assumes it is dead and quits. You would need to establish a heartbeat interval that is appropriate. The parent needs to check in more often than the child is checking it, or the child might check to soon and think the parent is gone.
It's possible to use isAlife if you somehow share parent thread object with child:
parent_thread = None
def child():
while True:
time.sleep(1)
if not parent_thread.isAlive():
break
print('child alife')
def parent():
t = threading.Thread(target=child)
t.start()
for i in range(10):
print('parent alife')
time.sleep(1)
parent_thread = threading.Thread(target=parent)
parent_thread.start()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With