[Python-Dev] PyThreadState_SetAsyncExc bug? (original) (raw)
tomer filiba tomerfiliba at gmail.com
Fri Aug 11 11:24:26 CEST 2006
- Previous message: [Python-Dev] __index__ clipping
- Next message: [Python-Dev] PyThreadState_SetAsyncExc bug?
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
while working on a library for raising exceptions in the context of another thread, i've come across a bug in PyThreadState_SetAsyncExc. if i raise an instance, sys.exc_info() confuses the exception value for the exception type, and the exception value is set None. if i raise the type itself, the interpreter creates an instance internally, but then i can't pass arguments to the exception.
code:
import threading import ctypes
def _async_raise(tid, excobj): res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(excobj)) if res == 0: raise ValueError("nonexistent 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, None) raise SystemError("PyThreadState_SetAsyncExc failed")
class Thread(threading.Thread): def raise_exc(self, excobj): assert self.isAlive(), "thread must be started" for tid, tobj in threading._active.items(): if tobj is self: _async_raise(tid, excobj) break
# the thread was alive when we entered the loop, but was not found
# in the dict, hence it must have been already terminated.
should we raise # an exception here? silently ignore?
def terminate(self):
self.raise_exc(SystemExit())
if name == "main": import time import sys
i_am_active = False
def f():
global i_am_active
i_am_active = True
try:
try:
while True:
time.sleep(0.01)
except IOError, ex:
print "IOError handler"
except TypeError, ex:
print "TypeError handler"
print "ex=", repr(ex)
typ, val, tb = sys.exc_info()
print "typ=", repr(typ)
print "val=", repr(val)
print "tb=", tb
finally:
i_am_active = False
t1 = Thread(target = f)
t1.start()
time.sleep(1)
t1.raise_exc(TypeError("blah blah"))
while i_am_active:
time.sleep(0.01)
print "!! thread terminated"
output:
TypeError handler ex= None typ= <exceptions.TypeError instance at 0x00C15D28> # should be the type val= None # should be the instance tb= <traceback object at 0x00C159E0> !! thread terminated
if i change: t1.raise_exc(TypeError("blah blah"))
to: t1.raise_exc(TypeError)
i get:
TypeError handler ex= <exceptions.TypeError instance at 0x00C159B8> typ= <class exceptions.TypeError at 0x00B945A0> val= <exceptions.TypeError instance at 0x00C159B8> tb= <traceback object at 0x00C15D00> !! thread terminated
but then of course i can't pass arguments to the exception
-tomer
- Previous message: [Python-Dev] __index__ clipping
- Next message: [Python-Dev] PyThreadState_SetAsyncExc bug?
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]