opened a new bug: http://sourceforge.net/tracker/index.php?func=detail&aid=1538556&group_id=5470&atid=105470
On 8/11/06, tomer filiba <[EMAIL PROTECTED]> wrote: > 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 > _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com