Killing a thread

Antoon Pardon apardon at forel.vub.ac.be
Mon Jun 12 05:17:32 EDT 2006


Op 2006-06-10, Carl J. Van Arsdall schreef <cvanarsdall at mvista.com>:
> Felipe Almeida Lessa wrote:
>> Em Sex, 2006-06-09 às 13:54 -0700, Manish Marathe escreveu:
>>   
>>> On 6/9/06, Fredrik Lundh <fredrik at pythonware.com> wrote:
>>>         Manish Marathe wrote:
>>>         
>>>         > I am creating threads using my self defined class which
>>>         inherits the
>>>         > threading.Thread class. I want to know how can I kill the
>>>         threads which
>>>         > are being created by the object of my self defined class. 
>>>         
>>>         you cannot kill a thread "from the outside"; you have to
>>>         design your
>>>         thread tasks so they can kill themselves, when asked to do
>>>         that.
>>>
>>> Thanks for the reply. So can a thread listen to an event i.e. can we
>>> send an event to the thread indicating to kill itself.
>>>     
>>
>> A plain simple boolean flag will certainly do the job. For example
>>
>>     def run(self):
>>         self.running = True
>>         while self.running:
>>             blah()
>>
>>     def stop(self):
>>         self.running = False
>>         
>>   
> Well, this works if your threads are able to poll.  If you had a thread 
> doing lengthy IO you could end up waiting a long time until the thread 
> gets an opportunity to kill itself.
>
> Are there any plans in the future to add the capability to kill threads 
> from the outside?

There already is some capability, (if you mean from the outside
that one thread can kill another) However for the momemt it is
only available in the C API. But with the ctypes interface
(which will be available with the stdlib from version 2.5)
you can provide this functionality in python.

> Better yet, an interruptable thread so instead of 
> using a polling loop you could send a DIE_THREAD_DIE signal or 
> something.  I think at present its not possible (or a really bad idea) 
> to put signal handlers in threads.  Anyone have thoughts on this?

It is indeed impossible to let a thread handle a signal. You can
set a handler in a thread but when a signal arrives.

But here is a class I toyed with, that can be used to throw
an exception in one thread from another. There are some
caveats however. It won't interupt C-calls. So if the
thread you want to raise the exception in, is in a C-extention,
the extention will have to finish before the exception will be
raised.

-----------------------------------------------------------------------

import ctypes
from time import sleep

SetAsyncExc = ctypes.pythonapi.PyThreadState_SetAsyncExc

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 throw(self, excpt):

    Nr = SetAsyncExc(self._thrd_id, ctypes.py_object(excpt))
    while Nr > 1:
      SetAsyncExc(self._thrd_id, None)
      sleep(0.1)
      Nr = SetAsyncExc(self._thrd_id, ctypes.py_object(excpt))

  def alarm(self, tm):

    alrm = threading.Timer(tm, self.throw, (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, self._thrd_id, "Finished"
      except Alarm:
        print self.id, self._thrd_id, "Interupted"
  
  lst = [Continue() for _ in xrange(10)]
  
  for T in lst:
    T.start()
  
  try:
    sleep(10)
  finally:
    for T in lst:
      T.throw(Alarm)


-- 
Antoon Pardon



More information about the Python-list mailing list