Created
April 17, 2012 16:02
-
-
Save liuw/2407154 to your computer and use it in GitHub Desktop.
Nasty hack to raise exception for other threads
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# liuw | |
# Nasty hack to raise exception for other threads | |
import ctypes # Calm down, this has become standard library since 2.5 | |
import threading | |
import time | |
NULL = 0 | |
def ctype_async_raise(thread_obj, exception): | |
found = False | |
target_tid = 0 | |
for tid, tobj in threading._active.items(): | |
if tobj is thread_obj: | |
found = True | |
target_tid = tid | |
break | |
if not found: | |
raise ValueError("Invalid thread object") | |
ret = ctypes.pythonapi.PyThreadState_SetAsyncExc(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") | |
print "Successfully set asynchronized exception for", target_tid | |
def f(): | |
try: | |
while True: | |
time.sleep(1) | |
finally: | |
print "Exited" | |
t = threading.Thread(target=f) | |
t.start() | |
print "Thread started" | |
print t.isAlive() | |
time.sleep(5) | |
ctype_async_raise(t, SystemExit) | |
t.join() | |
print t.isAlive() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@liuw May I add a small contribution ?
This hack is actually of a great help ! Hereafter a version in a multiprocessing context:
The idea is to have the main process starts an observer thread with pipe to a third independant process and then proceeding with non blocking operations.
The third process can interrupt our main process whenever it needs by the mean of the pipe and the thread observer.
If the main process should be waiting on sockets or sleep, I strongly advise to implement a timeout loop, which is a good practice what so ever.
PS: I did not sync the printing part.