iAdjunct
iAdjunct

Reputation: 2979

Throw an exception into another thread

This is not a duplicate of any question involving catching an exception thrown in one thread from another.

I have code which spawns a thread, and it goes off and does its own thing.

At some point in the future, I'd like to be able to throw one of two exceptions in the other thread (i.e. terminate and interrupt).

One way to do this is to have a variable shared and have the other thread periodically check if it should be killed. My preference is to not have the constraint that it checks (some of the code will be independent of the library doing the threading and won't have been written to check).

In my ideal solution, you may end up in a situation where, debugging, you might find that auto i = 1 + 1 throws an exception because another thread told your thread to throw and that's the line you just happened to be on at the time.

Is there a way I can do this?

Upvotes: 6

Views: 8383

Answers (2)

Erik Aronesty
Erik Aronesty

Reputation: 12877

Yes, it's possible to raise an exception into another thread.

I'm going to assume you know all the good reasons why this should not be done in a normal program. But as a part of, say, a test suite, a debug tool, or a program that is otherwise concerned with python internals, this might be helpful.

This is lifted, roughly from https://gist.github.com/liuw/2407154

import ctypes

def ctype_async_raise(target_tid, exception):
    ret = ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(target_tid), ctypes.py_object(exception))
    # ref: http://docs.python.org/c-api/init.html#PyThreadState_SetAsyncExc
    if ret == 0:
        raise ValueError("Invalid thread ID")
    elif ret > 1:
        # Huh? Why would we notify more than one threads?
        # Because we punch a hole into C level interpreter.
        # So it is better to clean up the mess.
        ctypes.pythonapi.PyThreadState_SetAsyncExc(target_tid, NULL)
        raise SystemError("PyThreadState_SetAsyncExc failed")

Upvotes: 8

Jeremy Friesner
Jeremy Friesner

Reputation: 73040

I don't think it makes conceptual sense to have an exception in thread A be caught in thread B, since a central concept of an exception is the unwinding of the stack, and thread A's stack is different from thread B's stack.

What you could do is throw the exception in thread A, have an exception handler in thread A catch the exception and handle it by somehow notifying thread B with the relevant details, and when thread B receives the notification is could respond by throwing its own exception that was similar to the exception originally thrown in thread A.

As for how to implement that notification and data transfer, you could use any of the usual cross-thread notification/communications mechanisms (shared atomic variables and polling, socketpair, pipe, mutex-guarded FIFO message queues, etc).

In my ideal solution, you may end up in a situation where, debugging, you might find that auto i = 1 + 1 throws an exception because another thread told your thread to throw and that's the line you just happened to be on at the time.

I think that is known as an asynchronous exception, and I don't think it is supported by standard C++. Microsoft has their structured exception handling (SEH) that sort of does that, but that's a proprietary/non-standard feature.

Upvotes: -3

Related Questions