sending thread exceptions (was Re: RELEASED Python 2.3.1)

Dominic oblivious at web.de
Fri Sep 26 16:30:31 EDT 2003


Well, first of all I agree with you that
a more traditional approach using queues
is better and more predictable.

And yes on a single CPU machine I was
thinking about stopping all "low priority"
threads.

This is somehow creaky and fragile but
you don't need a thread per "task" as
in your queue based alternative.

So you could have 3000 "tasks" and
one thread e.g.
However every "task" would need to recover
from it's injected exception which
is kind of unpredictable and hard to program.

I would not use such an architecture ;-)

Now to the delay:

from testx import interrupt
from thread import start_new_thread,exit
from time import sleep,ctime
from sys import stdin,stdout

def f():
	try:
		while 1:
			sleep(1)
			print 'hi there', ctime()
			stdout.flush()
	except StandardError:
		print 'done: ',ctime()
	exit()



tid=start_new_thread(f,())

sleep(1)

print 'initiate:',ctime()

interrupt(tid, StandardError())

print 'press any key'

stdin.readline()


result="""
[dh at hawk Python]$ python2.3 main.py
initiate: Sat Sep 27 00:11:30 2003
press any key
hi there Sat Sep 27 00:11:30 2003
hi there Sat Sep 27 00:11:31 2003
hi there Sat Sep 27 00:11:32 2003
hi there Sat Sep 27 00:11:33 2003
hi there Sat Sep 27 00:11:34 2003
hi there Sat Sep 27 00:11:35 2003
hi there Sat Sep 27 00:11:36 2003
hi there Sat Sep 27 00:11:37 2003
done:  Sat Sep 27 00:11:37 2003

[dh at hawk Python]$
"""

machine="""
Linux hawk 2.4.18-6mdk #1 Fri Mar 15 02:59:08 CET 2002 i686 unknown
"""

testx="""
# Pyrex version 0.8.2

cdef extern int PyThreadState_SetAsyncExc(long id, obj)


def interrupt(id, obj):
	        PyThreadState_SetAsyncExc(id, obj)
		
"""

As you can see it takes about 7 seconds until the
exception is injected.

Ciao,
  Dominic



> 
> 
>>While playing with the new feature I noticed that it
>>takes a long time (>3 seconds) until the exception is thrown.
>>In contrast to the possibility to interrupt the main thread
>>with interrupt_main which seems not to be delayed.
> 
> 
> Hmmmm... care to show exactly the code you've been trying?
> I get EXACTLY opposite results, as follows...:
> 
> 
> import time
> import thread
> import threadex
> 
> def saywhen():
>     for x in xrange(100000):
>         time.sleep(0.1)
> 
> def intemain():
>     global when_sent
>     when_sent = None
>     time.sleep(1.0)
>     when_sent = time.time()
>     thread.interrupt_main()
>     time.sleep(1.0)
> 
> im_delays = []
> for i in range(10):
>     tid = thread.start_new_thread(intemain, ())
>     try:
>         saywhen()
>     except:
>         when_received = time.time()
>     im_delays.append(when_received - when_sent)
> 
> def get_interrupted():
>     global when_received
>     when_received = None
>     try:
>         saywhen()
>     except:
>         when_received = time.time()
> 
> it_delays = []
> for i in range(10):
>     tid = thread.start_new_thread(get_interrupted, ())
>     time.sleep(1.0)
>     when_sent = time.time()
>     threadex.threadex(tid, KeyboardInterrupt)
>     time.sleep(1.0)
>     it_delays.append(when_received - when_sent)
> 
> main_id = thread.get_ident()
> def intemain1():
>     global when_sent
>     when_sent = None
>     time.sleep(1.0)
>     when_sent = time.time()
>     threadex.threadex(main_id, KeyboardInterrupt)
>     time.sleep(1.0)
> 
> im1_delays = []
> for i in range(10):
>     tid = thread.start_new_thread(intemain1, ())
>     try:
>         saywhen()
>     except:
>         when_received = time.time()
>     im1_delays.append(when_received - when_sent)
> 
> 
> im_delays.sort()
> im1_delays.sort()
> it_delays.sort()
> print 'IM:', im_delays
> print 'IT:', it_delays
> print 'IM1:', im1_delays
> 
> 
> 
> 
> Module threadex is a tiny interface exposing as 'threadex'
> the PyThreadState_SetAsyncExc function.  And the results on
> my Linux (Mandrake 9.1) box are as follows...:
> 
> 
> [alex at lancelot sae]$ python pai.py
> IM: [2.4993209838867188, 2.4998600482940674, 2.4998999834060669,
> 2.4999450445175171, 2.4999510049819946, 2.4999560117721558,
> 2.4999659061431885, 2.499967098236084, 2.4999990463256836,
> 2.5000520944595337]
> IT: [0.20004498958587646, 0.39922797679901123, 0.39999902248382568,
> 0.40000700950622559, 0.40000808238983154, 0.40002298355102539,
> 0.40002298355102539, 0.40002405643463135, 0.40003299713134766,
> 0.40004003047943115]
> IM1: [0.10003900527954102, 0.39957892894744873, 0.40000700950622559,
> 0.40000796318054199, 0.40001499652862549, 0.40002000331878662,
> 0.40003204345703125, 0.40003299713134766, 0.40004301071166992,
> 0.40005004405975342]
> [alex at lancelot sae]$
> 
> i.e., interrupt_main takes a very repeatable 2.5 seconds;
> PyThreadState_SetAsyncExc typically 0.4 seconds, whether it's
> going from main to secondary thread or viceversa, with occasional
> "low peaks" of 0.1 or 0.2 seconds.  Of course, it's quite
> possible that there may be something biased in my setup, or
> it may be a platform issue.  But I'd be quite curious to
> see the code you base your observation on.
> 
> 
> Alex
> 






More information about the Python-list mailing list