thread termination
--HG-- branch : aspn
This commit is contained in:
17
.project
Normal file
17
.project
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>aspn</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.python.pydev.PyDevBuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.python.pydev.pythonNature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
||||||
10
.pydevproject
Normal file
10
.pydevproject
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<?eclipse-pydev version="1.0"?>
|
||||||
|
|
||||||
|
<pydev_project>
|
||||||
|
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
|
||||||
|
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.6</pydev_property>
|
||||||
|
<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
|
||||||
|
<path>/aspn/src</path>
|
||||||
|
</pydev_pathproperty>
|
||||||
|
</pydev_project>
|
||||||
74
src/killable_thread.py
Normal file
74
src/killable_thread.py
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
# http://stackoverflow.com/questions/323972/is-there-any-way-to-kill-a-thread-in-python
|
||||||
|
|
||||||
|
''' KillableThread '''
|
||||||
|
|
||||||
|
# system imports
|
||||||
|
|
||||||
|
import ctypes
|
||||||
|
import inspect
|
||||||
|
import threading
|
||||||
|
|
||||||
|
# definitions
|
||||||
|
|
||||||
|
def _async_raise(tid, exctype):
|
||||||
|
'''Raises an exception in the threads with id tid'''
|
||||||
|
if not inspect.isclass(exctype):
|
||||||
|
raise TypeError("Only types can be raised (not instances)")
|
||||||
|
res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))
|
||||||
|
if res == 0:
|
||||||
|
raise ValueError("invalid thread id")
|
||||||
|
elif res != 1:
|
||||||
|
# """if it returns a number greater than one, you're in trouble,
|
||||||
|
# and you should call it again with exc=NULL to revert the effect"""
|
||||||
|
ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, 0)
|
||||||
|
raise SystemError("PyThreadState_SetAsyncExc failed")
|
||||||
|
|
||||||
|
|
||||||
|
class ThreadWithExc(threading.Thread):
|
||||||
|
'''A thread class that supports raising exception in the thread from another thread.
|
||||||
|
'''
|
||||||
|
def _get_my_tid(self):
|
||||||
|
"""determines this (self's) thread id
|
||||||
|
|
||||||
|
CAREFUL : this function is executed in the context of the caller thread,
|
||||||
|
to get the identity of the thread represented by this instance.
|
||||||
|
"""
|
||||||
|
if not self.isAlive():
|
||||||
|
raise threading.ThreadError("the thread is not active")
|
||||||
|
|
||||||
|
# do we have it cached?
|
||||||
|
if hasattr(self, "_thread_id"):
|
||||||
|
return self._thread_id
|
||||||
|
|
||||||
|
# no, look for it in the _active dict
|
||||||
|
for tid, tobj in threading._active.items():
|
||||||
|
if tobj is self:
|
||||||
|
self._thread_id = tid
|
||||||
|
return tid
|
||||||
|
|
||||||
|
# TODO : in python 2.6, there's a simpler way to do : self.ident ...
|
||||||
|
|
||||||
|
raise AssertionError("could not determine the thread's id")
|
||||||
|
|
||||||
|
def raiseExc(self, exctype):
|
||||||
|
"""Raises the given exception type in the context of this thread.
|
||||||
|
|
||||||
|
If the thread is busy in a system call (time.sleep(), socket.accept(), ...) the exception
|
||||||
|
is simply ignored.
|
||||||
|
|
||||||
|
If you are sure that your exception should terminate the thread, one way to ensure that
|
||||||
|
it works is:
|
||||||
|
t = ThreadWithExc( ... )
|
||||||
|
...
|
||||||
|
t.raiseExc( SomeException )
|
||||||
|
while t.isAlive():
|
||||||
|
time.sleep( 0.1 )
|
||||||
|
t.raiseExc( SomeException )
|
||||||
|
|
||||||
|
If the exception is to be caught by the thread, you need a way to check that your
|
||||||
|
thread has caught it.
|
||||||
|
|
||||||
|
CAREFUL : this function is executed in the context of the caller thread,
|
||||||
|
to raise an excpetion in the context of the thread represented by this instance.
|
||||||
|
"""
|
||||||
|
_async_raise( self._get_my_tid(), exctype )
|
||||||
25
src/stoppable_thread.py
Normal file
25
src/stoppable_thread.py
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
# http://stackoverflow.com/questions/323972/is-there-any-way-to-kill-a-thread-in-python
|
||||||
|
|
||||||
|
''' StoppableThread '''
|
||||||
|
|
||||||
|
# system imports
|
||||||
|
|
||||||
|
from threading import Event, Thread
|
||||||
|
|
||||||
|
# definitions
|
||||||
|
|
||||||
|
class StoppableThread(Thread):
|
||||||
|
"""Thread class with a stop() method. The thread itself has to check
|
||||||
|
regularly for the stopped() condition."""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(StoppableThread, self).__init__()
|
||||||
|
self._stop = Event()
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self._stop.set()
|
||||||
|
|
||||||
|
def stopped(self):
|
||||||
|
return self._stop.isSet()
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user