[Python-Dev] PyThreadState_SetAsyncExc bug?
tomer filiba
tomerfiliba at gmail.com
Fri Aug 11 11:24:26 CEST 2006
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
More information about the Python-Dev
mailing list