[Python-3000] threading, part 2

Tim Peters tim.peters at gmail.com
Mon Aug 14 21:15:30 CEST 2006


[tomer filiba]
>> i mailed this to several people separately, but then i thought it could
>> benefit the entire group:
>>
>> http://sebulba.wikispaces.com/recipe+thread2
>>
>> it's an implementation of the proposed " thread.raise_exc",
>> ...

[Guido]
> Cool. Question: what's the problem with raising exception instances?

See

    http://mail.python.org/pipermail/python-dev/2006-August/068165.html

Short course:  in ceval.c,

    x = tstate->async_exc;
    ...
    PyErr_SetNone(x);

That is, with the current code it's only possible to set the exception
type via PyThreadState_SetAsyncExc(); the exception value is forced to
None/NULL.  What was the intent ;-)?

Example:

"""
from time import sleep
import ctypes, thread, sys, threading

setexc = ctypes.pythonapi.PyThreadState_SetAsyncExc

f_done = threading.Event()
def f():
    try:
        while 1:
            time.sleep(1)
    finally:
        f_done.set()

tid = thread.start_new_thread(f, ())
exc = ValueError("13")

setexc(ctypes.c_long(tid),
       ctypes.py_object(exc))

f_done.wait()
"""

Output:

Unhandled exception in thread started by <function f at 0x009E8370>
Traceback (most recent call last):
  File "setexc.py", line 12, in f
    f_done.set()
  File "C:\Code\python\lib\threading.py", line 351, in set
    self.__cond.release()
SystemError: 'finally' pops bad exception


Change `exc` to, e.g.,

exc = ValueError

and then it's fine:

Unhandled exception in thread started by <function f at 0x009E8370>
Traceback (most recent call last):
  File "setexc.py", line 12, in f
    f_done.set()
  File "C:\Code\python\lib\threading.py", line 349, in set
    self.__cond.notifyAll()
  File "C:\Code\python\lib\threading.py", line 265, in notifyAll
    self.notify(len(self.__waiters))
  File "C:\Code\python\lib\threading.py", line 258, in notify
    waiter.release()
ValueError


More information about the Python-3000 mailing list