[pygtk] shutting down worker threads
Antoon Pardon
Antoon.Pardon at rece.vub.ac.be
Fri Mar 31 18:51:14 WST 2006
On Wed, Mar 29, 2006 at 01:52:01PM -0600, Jason Pepas wrote:
> On Wednesday 29 March 2006 12:21 pm, you wrote:
> > Jason Pepas napisa?(a):
> > > When I want to stop my program, how do I interrupt what the worker
> > > threads are doing to tell them it is time to stop?
> >
> > You can poll shared object for "stop flag" in worker thread (in
> > something like "timer object"). And besides that, you have no other
> > options in Python.
>
> Damn, I was hoping to be able to use interruption instead of polling. Oh
> well...
You can, but doing so has some caveats.
The following is only tested on linux, uses ctypes and will
only interrupt python code, so it won't interrupt a thread while in
a C-extention. It provides an Xthread class with a raize method.
This method can be used from an other thread to raise an exception
in this thread and thus interrupt it.
----
import ctypes
from time import sleep
class TimeOut(Exception):
pass
class Alarm(Exception):
pass
import threading
class Xthread(threading.Thread):
def start(self):
self.__original_run = self.run
self.run = self.__run
threading.Thread.start(self)
def __run(self):
self._thrd_id = threading._get_ident()
try:
self.__original_run()
finally:
self.run = self.__original_run
def raize(self, excpt):
Nr = ctypes.pythonapi.PyThreadState_SetAsyncExc(self._thrd_id,
ctypes.py_object(excpt))
#print self.id , "Exception Thrown" , Nr
while Nr > 1:
#print self.id , "Exception Canceled" , Nr
ctypes.pythonapi.PyThreadState_SetAsyncExc(self._thrd_id, None)
sleep(0.1)
Nr = ctypes.pythonapi.PyThreadState_SetAsyncExc(self._thrd_id,
ctypes.py_object(excpt))
#if Nr == 0:
# print self.id , "Exception Canceled" , Nr
# ctypes.pythonapi.PyThreadState_SetAsyncExc(self._thrd_id, None)
def alarm(self, tm):
alrm = threading.Timer(tm, self.raize, (TimeOut,))
alrm.start()
return alrm
if __name__ == "__main__":
import os
from random import randint
class Continue(Xthread):
def run(self):
self.id = os.getpid()
print self.id, self._thrd_id, "Begin"
i = 0
try:
for _ in xrange(randint(0,20)):
for e in xrange(4 * 100000):
i = i + e
print self.id, "Finished"
except Alarm:
print self.id, "Interupted"
lst = [Continue() for _ in xrange(10)]
for T in lst:
T.start()
try:
sleep(10)
finally:
for T in lst:
T.raize(Alarm)
More information about the pygtk
mailing list