By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,621 Members | 1,101 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,621 IT Pros & Developers. It's quick & easy.

Re: How to kill a thread?

P: n/a
John Dohn wrote:
Hi there,

How can I kill a threading.Thread subclass from MainThread?

My threads are waiting for data in Queue.get() method:
class MyThread(threading.Thread):
def run(self):
while True:
data = queue.get() # <- here it waits most of the time
... process data

From the main thread I start several working threads:
thr = MyThread()
thr.start()
... feed the queue
and at the end for each thread I'd like to do something like thr.kill()
or thr.stop() or thr.destroy() or ... you got the point. I can't figure
out how.

Is there a way to do it?
When I do this, I put a special value in the queue (like None) and in
the worker thread, check for the special value and exit if found.

Threads can also be marked as "daemon threads" (see docs for
threading.Thread objects). This will make the application terminate if
only "daemon threads" are left.

So best would probably be soemthing like

- call setDaemon() when creating worker threads
- ...
- send all worker/daemon threads None via queue
- wait some time, like time.sleep(1.0), to let daemon exit themselves
- exit main application

-- Gerhard

Jun 27 '08 #1
Share this Question
Share on Google+
20 Replies


P: n/a
It's always been my understanding that you can't forcibly kill a thread
in Python (at least not in a portable way). The best you can do is
politely ask it to die, IIRC.

--
code.py: A blog about life, the universe, and Python

http://pythonista.wordpress.com
** Posted from http://www.teranews.com **
Jun 27 '08 #2

P: n/a
On Jun 6, 12:44 pm, The Pythonista <n...@this.timewrote:
It's always been my understanding that you can't forcibly kill a thread
in Python (at least not in a portable way). The best you can do is
politely ask it to die, IIRC.
Inherently, the best you can do in most languages is ask them politely
to die. Otherwise you'll leave locks and various other datastructures
in an inconvenient state, which is too complex to handle correctly.
The exception is certain functional languages, which aren't capable of
having threads and complex state in the same sense.

However, you could go quite far with a standardized mechanism of
politely asking threads to die. For instance, all blocking I/O
functions could be made to support it. This is how cancellation works
in python-safethread.
Jun 27 '08 #3

P: n/a
Would it be possible for a 3rd-party threading library to an
'interruptible' version of Queue?

The same methods as the normal Queue, but when you call a new .kill()
method on the queue, all the threads locking on the queue get a
"QueueKilled" exception thrown.

It might be as simple as a Queue wrapper where .kill() adds a speciall
Killed value to the queue, and the .get() wrapper throws a QueueKilled
exception (after re-putting Killed) when it reads Killed.

Locking for queues with a limited size is more complicated. Maybe
..kill() can also set an .killed attribute, and pop anything already in
the queue before putting Killed. Then when the put() wrapper unlocks,
it checks if .killed is set, and throws a QueueKilled exception.

One side-effect is that the queue becomes unusable (get & put now
immediately throw QueueKilled), unless you make a .unkill() method.

David
Jun 27 '08 #4

P: n/a
David <wi******@gmail.comwrote:
Would it be possible for a 3rd-party threading library to an
'interruptible' version of Queue?

The same methods as the normal Queue, but when you call a new .kill()
method on the queue, all the threads locking on the queue get a
"QueueKilled" exception thrown.

It might be as simple as a Queue wrapper where .kill() adds a speciall
Killed value to the queue, and the .get() wrapper throws a QueueKilled
exception (after re-putting Killed) when it reads Killed.
There seem to me to be 2 basic types of threads - I'll call them
client threads and server threads.

A client thread listens on a Queue for its instructions and replies
via a different Queue, or via Queues passed in in its instructions.
That kind of thread can easily have an instruction which means quit.
When it isn't processing instructions there is a nice clean moment for
it to quit. However if the processing takes a long time then there
will be a long wait for the thread to die. This is the scenario
described above.

The server type thread is processing all the time. Every now and
again it sends its results via a Queue. An example of this type of
thread might be one listening on a socket. This type of thread has no
nice moment to listen for instructions to quit as it might well be
blocked on something else (eg listening to a socket). To make this
type of thread kill nicely you have to go back to breaking up your
work into chunks (eg polling the socket asynchronously) and polling
the command queue to wait for your quit instruction which is wastefull
of CPU resources.

So it seems to me that there isn't a good solution to killing python
threads of either type, other than coding them carefully and checking
for quit instructions regularly.

You can kill them using the internal python API and ctypes, but you
run the risk of leaving things in an inconsistent state which is why
that API isn't exposed.

Here is an attempt at a killable thread

http://aspn.activestate.com/ASPN/Coo.../Recipe/496960

and

http://sebulba.wikispaces.com/recipe+thread2

Read the caveats!

--
Nick Craig-Wood <ni**@craig-wood.com-- http://www.craig-wood.com/nick
Jun 27 '08 #5

P: n/a
On 2008-06-07, Rhamphoryncus <rh****@gmail.comwrote:
On Jun 6, 12:44 pm, The Pythonista <n...@this.timewrote:
>It's always been my understanding that you can't forcibly kill a thread
in Python (at least not in a portable way). The best you can do is
politely ask it to die, IIRC.

Inherently, the best you can do in most languages is ask them politely
to die. Otherwise you'll leave locks and various other datastructures
in an inconvenient state, which is too complex to handle correctly.
The exception is certain functional languages, which aren't capable of
having threads and complex state in the same sense.
Well it would of course depend on what is considered asking politely?

If one thread could cause an exception being thrown in an other thread,
would this be considered a polite way to ask? Would it be considered
an acceptable way?

--
Antoon Pardon
Jun 27 '08 #6

P: n/a
On 2008-06-07, David <wi******@gmail.comwrote:
Would it be possible for a 3rd-party threading library to an
'interruptible' version of Queue?

The same methods as the normal Queue, but when you call a new .kill()
method on the queue, all the threads locking on the queue get a
"QueueKilled" exception thrown.
I have done something similar. The idea was that threads had to open
a queue before they could access it. If the last thread who had the
queue open in write mode, closed the queue, a reader trying to get
an element from an empty queue would have an "EOInformation" exception
raised.

--
Antoon Pardon
Jun 27 '08 #7

P: n/a
On Jun 9, 5:33 am, Antoon Pardon <apar...@forel.vub.ac.bewrote:
On 2008-06-07, Rhamphoryncus <rha...@gmail.comwrote:
On Jun 6, 12:44 pm, The Pythonista <n...@this.timewrote:
It's always been my understanding that you can't forcibly kill a thread
in Python (at least not in a portable way). The best you can do is
politely ask it to die, IIRC.
Inherently, the best you can do in most languages is ask them politely
to die. Otherwise you'll leave locks and various other datastructures
in an inconvenient state, which is too complex to handle correctly.
The exception is certain functional languages, which aren't capable of
having threads and complex state in the same sense.

Well it would of course depend on what is considered asking politely?

If one thread could cause an exception being thrown in an other thread,
would this be considered a polite way to ask? Would it be considered
an acceptable way?
The exception must not be raised until a point explicitly designed as
safe is hit. Otherwise, any function that manipulates data you'll
still use will potentially be buggered. Consider sys.stdout: codecs,
buffering, lots to go wrong.
Jun 27 '08 #8

P: n/a
On Jun 9, 9:20*pm, Rhamphoryncus <rha...@gmail.comwrote:
On Jun 9, 5:33 am, Antoon Pardon <apar...@forel.vub.ac.bewrote:
On 2008-06-07, Rhamphoryncus <rha...@gmail.comwrote:
On Jun 6, 12:44 pm, The Pythonista <n...@this.timewrote:
>It's always been my understanding that you can't forcibly kill a thread
>in Python (at least not in a portable way). *The best you can do is
>politely ask it to die, IIRC.
Inherently, the best you can do in most languages is ask them politely
to die. *Otherwise you'll leave locks and various other datastructures
in an inconvenient state, which is too complex to handle correctly.
The exception is certain functional languages, which aren't capable of
having threads and complex state in the same sense.
Well it would of course depend on what is considered asking politely?
If one thread could cause an exception being thrown in an other thread,
would this be considered a polite way to ask? Would it be considered
an acceptable way?

The exception must not be raised until a point explicitly designed as
safe is hit. *Otherwise, any function that manipulates data you'll
still use will potentially be buggered. *Consider sys.stdout: codecs,
buffering, lots to go wrong.

Java and .NET both have ways of killing threads. They both work by
raising a 'ThreadAbort' (or similar) exception in the target thread.
In early implementations they both suffered from a similar problem.
You could protect locks (etc) by having a finally block that would
release all resources as needed - but what happens if the thread abort
exception is raised *inside* the finally block?

Java responded by deprecating thread aborting. .NET responded by
ensuring that a thread abort exception would never be raised inside a
finally block - if that happened the exception would only be raised
once the code has left the finally block.

Aborting threads in .NET can be extremely useful. Politely asking a
thread to die is no good if the task the thread is executing is
extremely coarse grained - it may not be able to respond to the
request for some time. If your code is structured correctly
(performing a long running background calculation for example) then
you may *know* that you can kill it without problems, but Python has
no native API to do this.

Michael Foord
http://www.ironpythoninaction.com/
Jun 27 '08 #9

P: n/a
On Jun 9, 2:52 pm, Fuzzyman <fuzzy...@gmail.comwrote:
On Jun 9, 9:20 pm, Rhamphoryncus <rha...@gmail.comwrote:
On Jun 9, 5:33 am, Antoon Pardon <apar...@forel.vub.ac.bewrote:
On 2008-06-07, Rhamphoryncus <rha...@gmail.comwrote:
On Jun 6, 12:44 pm, The Pythonista <n...@this.timewrote:
It's always been my understanding that you can't forcibly kill a thread
in Python (at least not in a portable way). The best you can do is
politely ask it to die, IIRC.
Inherently, the best you can do in most languages is ask them politely
to die. Otherwise you'll leave locks and various other datastructures
in an inconvenient state, which is too complex to handle correctly.
The exception is certain functional languages, which aren't capable of
having threads and complex state in the same sense.
Well it would of course depend on what is considered asking politely?
If one thread could cause an exception being thrown in an other thread,
would this be considered a polite way to ask? Would it be considered
an acceptable way?
The exception must not be raised until a point explicitly designed as
safe is hit. Otherwise, any function that manipulates data you'll
still use will potentially be buggered. Consider sys.stdout: codecs,
buffering, lots to go wrong.

Java and .NET both have ways of killing threads. They both work by
raising a 'ThreadAbort' (or similar) exception in the target thread.
In early implementations they both suffered from a similar problem.
You could protect locks (etc) by having a finally block that would
release all resources as needed - but what happens if the thread abort
exception is raised *inside* the finally block?

Java responded by deprecating thread aborting. .NET responded by
ensuring that a thread abort exception would never be raised inside a
finally block - if that happened the exception would only be raised
once the code has left the finally block.

Aborting threads in .NET can be extremely useful. Politely asking a
thread to die is no good if the task the thread is executing is
extremely coarse grained - it may not be able to respond to the
request for some time. If your code is structured correctly
(performing a long running background calculation for example) then
you may *know* that you can kill it without problems, but Python has
no native API to do this.
So how does .NET deal with the sys.stdout corruption? Does it?

If you've carefully written your code to use only safe primitives and
local state (discarded if interrupted) then yes, it could be
interruptible. At this point you could specially mark that block of
code as safe, leaving the vast majority of other code unsafe by
default. Then again, since you're going to the trouble of carefully
designing and auditing your code you could just make it cancellable
like blocking I/O should be - just by polling a flag at key points
(and you're CPU-bound anyway, so it's not expensive.)

The only place I know of that you *need* arbitrary interruption is
hitting CTRL-C in the interactive interpreter. At this point it's a
debugging tool though, so the risk of weirdness is acceptable.
Jun 27 '08 #10

P: n/a
On 2008-06-09, Rhamphoryncus <rh****@gmail.comwrote:
On Jun 9, 5:33 am, Antoon Pardon <apar...@forel.vub.ac.bewrote:
>On 2008-06-07, Rhamphoryncus <rha...@gmail.comwrote:
On Jun 6, 12:44 pm, The Pythonista <n...@this.timewrote:
It's always been my understanding that you can't forcibly kill a thread
in Python (at least not in a portable way). The best you can do is
politely ask it to die, IIRC.
Inherently, the best you can do in most languages is ask them politely
to die. Otherwise you'll leave locks and various other datastructures
in an inconvenient state, which is too complex to handle correctly.
The exception is certain functional languages, which aren't capable of
having threads and complex state in the same sense.

Well it would of course depend on what is considered asking politely?

If one thread could cause an exception being thrown in an other thread,
would this be considered a polite way to ask? Would it be considered
an acceptable way?

The exception must not be raised until a point explicitly designed as
safe is hit. Otherwise, any function that manipulates data you'll
still use will potentially be buggered. Consider sys.stdout: codecs,
buffering, lots to go wrong.
I don't see the point. Exceptions are raised now without the ability
of an explicitly designed safe point. If something unexpected happens
your code can raise an exception and leave your data buggered too if
you didn't anticipate it propely.

--
Antoon Pardon
Jun 27 '08 #11

P: n/a
On Jun 10, 1:55 am, Antoon Pardon <apar...@forel.vub.ac.bewrote:
On 2008-06-09, Rhamphoryncus <rha...@gmail.comwrote:
On Jun 9, 5:33 am, Antoon Pardon <apar...@forel.vub.ac.bewrote:
On 2008-06-07, Rhamphoryncus <rha...@gmail.comwrote:
On Jun 6, 12:44 pm, The Pythonista <n...@this.timewrote:
It's always been my understanding that you can't forcibly kill a thread
in Python (at least not in a portable way). The best you can do is
politely ask it to die, IIRC.
Inherently, the best you can do in most languages is ask them politely
to die. Otherwise you'll leave locks and various other datastructures
in an inconvenient state, which is too complex to handle correctly.
The exception is certain functional languages, which aren't capable of
having threads and complex state in the same sense.
Well it would of course depend on what is considered asking politely?
If one thread could cause an exception being thrown in an other thread,
would this be considered a polite way to ask? Would it be considered
an acceptable way?
The exception must not be raised until a point explicitly designed as
safe is hit. Otherwise, any function that manipulates data you'll
still use will potentially be buggered. Consider sys.stdout: codecs,
buffering, lots to go wrong.

I don't see the point. Exceptions are raised now without the ability
of an explicitly designed safe point. If something unexpected happens
your code can raise an exception and leave your data buggered too if
you didn't anticipate it propely.
Although in theory you could get any exception at any point, in
practise you shouldn't unless your program is broken. If it is broken
the exceptions shouldn't be caught and should cause the program to
terminate, so the harm is reduced. The exceptions that should happen
(such as IOError) should be from predicted points, and anticipated.

A notable exception is MemoryError, which can show up from anywhere at
any time. Nobody's come up with a solution to that one, so we usually
just let the program die.

Cancelling a thread implies your program will continue. Otherwise
you'd just exit the whole process (either via _exit() or via daemon
threads.)
Jun 27 '08 #12

P: n/a
On Jun 10, 2:03*am, Rhamphoryncus <rha...@gmail.comwrote:
On Jun 9, 2:52 pm, Fuzzyman <fuzzy...@gmail.comwrote:
On Jun 9, 9:20 pm, Rhamphoryncus <rha...@gmail.comwrote:
On Jun 9, 5:33 am, Antoon Pardon <apar...@forel.vub.ac.bewrote:
On 2008-06-07, Rhamphoryncus <rha...@gmail.comwrote:
On Jun 6, 12:44 pm, The Pythonista <n...@this.timewrote:
>It's always been my understanding that you can't forcibly kill a thread
>in Python (at least not in a portable way). *The best you can do is
>politely ask it to die, IIRC.
Inherently, the best you can do in most languages is ask them politely
to die. *Otherwise you'll leave locks and various other datastructures
in an inconvenient state, which is too complex to handle correctly..
The exception is certain functional languages, which aren't capable of
having threads and complex state in the same sense.
Well it would of course depend on what is considered asking politely?
If one thread could cause an exception being thrown in an other thread,
would this be considered a polite way to ask? Would it be considered
an acceptable way?
The exception must not be raised until a point explicitly designed as
safe is hit. *Otherwise, any function that manipulates data you'll
still use will potentially be buggered. *Consider sys.stdout: codecs,
buffering, lots to go wrong.
Java and .NET both have ways of killing threads. They both work by
raising a 'ThreadAbort' (or similar) exception in the target thread.
In early implementations they both suffered from a similar problem.
You could protect locks (etc) by having a finally block that would
release all resources as needed - but what happens if the thread abort
exception is raised *inside* the finally block?
Java responded by deprecating thread aborting. .NET responded by
ensuring that a thread abort exception would never be raised inside a
finally block - if that happened the exception would only be raised
once the code has left the finally block.
Aborting threads in .NET can be extremely useful. Politely asking a
thread to die is no good if the task the thread is executing is
extremely coarse grained - it may not be able to respond to the
request for some time. If your code is structured correctly
(performing a long running background calculation for example) then
you may *know* that you can kill it without problems, but Python has
no native API to do this.

So how does .NET deal with the sys.stdout corruption? *Does it?
That has never been an issue for us.
If you've carefully written your code to use only safe primitives and
local state (discarded if interrupted) then yes, it could be
interruptible. *At this point you could specially mark that block of
code as safe, leaving the vast majority of other code unsafe by
default. *Then again, since you're going to the trouble of carefully
designing and auditing your code you could just make it cancellable
like blocking I/O should be - just by polling a flag at key points
(and you're CPU-bound anyway, so it's not expensive.)

The only place I know of that you *need* arbitrary interruption is
hitting CTRL-C in the interactive interpreter. *At this point it's a
debugging tool though, so the risk of weirdness is acceptable.
We use background threads for long running calculations that we know
are safe to abort. Resources that need protecting we do with finally
blocks which the thread abort honours.

The calculation is 'coarse grained' (it can call into .NET APIs that
can take a relatively long time to return) - so polling for exit
wouldn't work anyway. We also run user code and can't expect their
code to poll for exit conditions.

This system works fine for us. We had fun syncing results back when
the calculation terminates (race conditions if a new one needs to
start just as the old one ends) - but that is the fun of threads in
the first place and nothing to do with how we terminate calculations
early.

Michael Foord
http://www.ironpythoninaction.com/
Jun 27 '08 #13

P: n/a
On Jun 10, 3:41 pm, Fuzzyman <fuzzy...@gmail.comwrote:
On Jun 10, 2:03 am, Rhamphoryncus <rha...@gmail.comwrote:
So how does .NET deal with the sys.stdout corruption? Does it?

That has never been an issue for us.
Of course. It's far more likely to hit the underlying blocked I/O
than the buffer management, unless it's doing a great deal of I/O. Or
alternatively, they're using some other mechanism to prevent
interruption during buffer management.

If you've carefully written your code to use only safe primitives and
local state (discarded if interrupted) then yes, it could be
interruptible. At this point you could specially mark that block of
code as safe, leaving the vast majority of other code unsafe by
default. Then again, since you're going to the trouble of carefully
designing and auditing your code you could just make it cancellable
like blocking I/O should be - just by polling a flag at key points
(and you're CPU-bound anyway, so it's not expensive.)
The only place I know of that you *need* arbitrary interruption is
hitting CTRL-C in the interactive interpreter. At this point it's a
debugging tool though, so the risk of weirdness is acceptable.

We use background threads for long running calculations that we know
are safe to abort. Resources that need protecting we do with finally
blocks which the thread abort honours.
How does that protect code like this?

f = open('somefile', 'w')
# interruption here
try:
...
finally:
...

The calculation is 'coarse grained' (it can call into .NET APIs that
can take a relatively long time to return) - so polling for exit
wouldn't work anyway. We also run user code and can't expect their
code to poll for exit conditions.
Do those .NET get interrupted at arbitrary points? Is this
"untrusted" user code also audited for correctness? (Although I'd bet
you simply document what you do and blame the user if something
breaks.)

I'm not saying it can't be made to work in your specific case - it
likely does work well for you. I'm saying it can't work *in
general*. Stretching it out for general use turns those little cracks
into massive canyons. A language needs a general mechanism that does
work - such as a polite cancellation API.
Jun 27 '08 #14

P: n/a
On 2008-06-10, Rhamphoryncus <rh****@gmail.comwrote:
On Jun 10, 1:55 am, Antoon Pardon <apar...@forel.vub.ac.bewrote:
>On 2008-06-09, Rhamphoryncus <rha...@gmail.comwrote:
On Jun 9, 5:33 am, Antoon Pardon <apar...@forel.vub.ac.bewrote:
On 2008-06-07, Rhamphoryncus <rha...@gmail.comwrote:
On Jun 6, 12:44 pm, The Pythonista <n...@this.timewrote:
It's always been my understanding that you can't forcibly kill a thread
in Python (at least not in a portable way). The best you can do is
politely ask it to die, IIRC.
Inherently, the best you can do in most languages is ask them politely
to die. Otherwise you'll leave locks and various other datastructures
in an inconvenient state, which is too complex to handle correctly.
The exception is certain functional languages, which aren't capable of
having threads and complex state in the same sense.
>Well it would of course depend on what is considered asking politely?
>If one thread could cause an exception being thrown in an other thread,
would this be considered a polite way to ask? Would it be considered
an acceptable way?
The exception must not be raised until a point explicitly designed as
safe is hit. Otherwise, any function that manipulates data you'll
still use will potentially be buggered. Consider sys.stdout: codecs,
buffering, lots to go wrong.

I don't see the point. Exceptions are raised now without the ability
of an explicitly designed safe point. If something unexpected happens
your code can raise an exception and leave your data buggered too if
you didn't anticipate it propely.

Although in theory you could get any exception at any point, in
practise you shouldn't unless your program is broken. If it is broken
the exceptions shouldn't be caught and should cause the program to
terminate, so the harm is reduced. The exceptions that should happen
(such as IOError) should be from predicted points, and anticipated.
In pratice you can schedule an alarm and have the alarm handler raise
an exception in your code. It is the resposibility of the developer to
write his code in such a way that it can handle such an interruption
as it should.

Given that the above is already possible I don't see why we should
protect the programmer from such an asynchronous exception merely
because they can be raised from an other thread.

--
Antoon Pardon
Jun 27 '08 #15

P: n/a
On Jun 11, 6:56 am, Rhamphoryncus <rha...@gmail.comwrote:
On Jun 10, 3:41 pm, Fuzzyman <fuzzy...@gmail.comwrote:
On Jun 10, 2:03 am, Rhamphoryncus <rha...@gmail.comwrote:
So how does .NET deal with the sys.stdout corruption? Does it?
That has never been an issue for us.

Of course. It's far more likely to hit the underlying blocked I/O
than the buffer management, unless it's doing a great deal of I/O. Or
alternatively, they're using some other mechanism to prevent
interruption during buffer management.
If you've carefully written your code to use only safe primitives and
local state (discarded if interrupted) then yes, it could be
interruptible. At this point you could specially mark that block of
code as safe, leaving the vast majority of other code unsafe by
default. Then again, since you're going to the trouble of carefully
designing and auditing your code you could just make it cancellable
like blocking I/O should be - just by polling a flag at key points
(and you're CPU-bound anyway, so it's not expensive.)
The only place I know of that you *need* arbitrary interruption is
hitting CTRL-C in the interactive interpreter. At this point it's a
debugging tool though, so the risk of weirdness is acceptable.
We use background threads for long running calculations that we know
are safe to abort. Resources that need protecting we do with finally
blocks which the thread abort honours.

How does that protect code like this?

f = open('somefile', 'w')
# interruption here
try:
...
finally:
...
How does it *not* protect you if you write this instead:

f = None
try:
f = open('somefile', 'w')
...
finally:
if f is not None:
...
The calculation is 'coarse grained' (it can call into .NET APIs that
can take a relatively long time to return) - so polling for exit
wouldn't work anyway. We also run user code and can't expect their
code to poll for exit conditions.

Do those .NET get interrupted at arbitrary points? Is this
"untrusted" user code also audited for correctness? (Although I'd bet
you simply document what you do and blame the user if something
breaks.)
We don't audit our user code - of course. We do document and assist
them as necessary. Changing to a more restrictive model still wouldn't
meet our use case and put *more* of a burden on our users.

Our situation is not the only one. In general there are situations
where you may want to put a long running calulcation on a background
thread and you *know* that it is safe to interrupt - but Python
currently won't let you.
I'm not saying it can't be made to work in your specific case - it
likely does work well for you. I'm saying it can't work *in
general*. Stretching it out for general use turns those little cracks
into massive canyons. A language needs a general mechanism that does
work - such as a polite cancellation API.

Neither *works in general* - polite cancellation *doesn't* work for
our us. That's my point - you probably want *both* for different use
cases. :-)
Michael Foord
http://www.ironpythoninaction.com/
Jun 27 '08 #16

P: n/a
On Jun 7, 6:30*am, Nick Craig-Wood <n...@craig-wood.comwrote:
Here is an attempt at a killable thread

*http://aspn.activestate.com/ASPN/Coo.../Recipe/496960

and

*http://sebulba.wikispaces.com/recipe+thread2
I use this recipe in paste.httpserver to kill wedged threads, and it
works okay. It seems to kill threads that are genuinely wedged, e.g.,
if you try to read past the end of a socket. It takes surprisingly
long, up to a minute to actually send the exception to a thread. But
it's just a normal exception and seems to act reasonably.

Obviously this is not a great system, but it's better than having a
background process hang because of problem code elsewhere in the
system. It also isn't any worse than kill -9, which is ultimately
what a multiprocess system has to do to misbehaving worker processes.
Still, to try to mitigate problems with this I set up a supervisor
process and if there is a lot of problems with worker threads I'll
have the entire process self-destruct so it can be restarted by the
supervisor.

The code is rather... organic in its development. But you can see it
in the ThreadPool here:
http://svn.pythonpaste.org/Paste/tru.../httpserver.py

Ian
Jun 27 '08 #17

P: n/a
On Jun 11, 7:56 am, Fuzzyman <fuzzy...@gmail.comwrote:
On Jun 11, 6:56 am, Rhamphoryncus <rha...@gmail.comwrote:
On Jun 10, 3:41 pm, Fuzzyman <fuzzy...@gmail.comwrote:
On Jun 10, 2:03 am, Rhamphoryncus <rha...@gmail.comwrote:
How does that protect code like this?
f = open('somefile', 'w')
# interruption here
try:
...
finally:
...

How does it *not* protect you if you write this instead:

f = None
try:
f = open('somefile', 'w')
...
finally:
if f is not None:
...
Yeah, that should be safe, so long as the open call itself is
protected.

The calculation is 'coarse grained' (it can call into .NET APIs that
can take a relatively long time to return) - so polling for exit
wouldn't work anyway. We also run user code and can't expect their
code to poll for exit conditions.
Do those .NET get interrupted at arbitrary points? Is this
"untrusted" user code also audited for correctness? (Although I'd bet
you simply document what you do and blame the user if something
breaks.)

We don't audit our user code - of course. We do document and assist
them as necessary. Changing to a more restrictive model still wouldn't
meet our use case and put *more* of a burden on our users.

Our situation is not the only one. In general there are situations
where you may want to put a long running calulcation on a background
thread and you *know* that it is safe to interrupt - but Python
currently won't let you.
I'm not saying it can't be made to work in your specific case - it
likely does work well for you. I'm saying it can't work *in
general*. Stretching it out for general use turns those little cracks
into massive canyons. A language needs a general mechanism that does
work - such as a polite cancellation API.

Neither *works in general* - polite cancellation *doesn't* work for
our us. That's my point - you probably want *both* for different use
cases. :-)
Yeah, but mine's less icky. ;)

I think the ideal for you would be a separate process. I'd also
suggest a restricted VM only in a thread, but that probably wouldn't
work for those long-running .NET APIs. Now, if those long-
running .NET APIs did polite cancellation, then you could combine that
with a restricted VM to get what you need.

I think what bothers me is, even if those external APIs support polite
cancellation properly, your forced interruptions will bleed over and
mess them up. There needs to be a way of containing it better.
Writing them in another language (as C is used for most of Python's
builtins today) isn't a reasonable requirement.
Jun 27 '08 #18

P: n/a
On Jun 11, 6:49*pm, Rhamphoryncus <rha...@gmail.comwrote:
On Jun 11, 7:56 am, Fuzzyman <fuzzy...@gmail.comwrote:
On Jun 11, 6:56 am, Rhamphoryncus <rha...@gmail.comwrote:
On Jun 10, 3:41 pm, Fuzzyman <fuzzy...@gmail.comwrote:
On Jun 10, 2:03 am, Rhamphoryncus <rha...@gmail.comwrote:
How does that protect code like this?
f = open('somefile', 'w')
# interruption here
try:
* * ...
finally:
* * ...
How does it *not* protect you if you write this instead:
f = None
try:
* f = open('somefile', 'w')
* ...
finally:
* if f is not None:
* * ...

Yeah, that should be safe, so long as the open call itself is
protected.
The calculation is 'coarse grained' (it can call into .NET APIs that
can take a relatively long time to return) - so polling for exit
wouldn't work anyway. We also run user code and can't expect their
code to poll for exit conditions.
Do those .NET get interrupted at arbitrary points? *Is this
"untrusted" user code also audited for correctness? *(Although I'd bet
you simply document what you do and blame the user if something
breaks.)
We don't audit our user code - of course. We do document and assist
them as necessary. Changing to a more restrictive model still wouldn't
meet our use case and put *more* of a burden on our users.
Our situation is not the only one. In general there are situations
where you may want to put a long running calulcation on a background
thread and you *know* that it is safe to interrupt - but Python
currently won't let you.
I'm not saying it can't be made to work in your specific case - it
likely does work well for you. *I'm saying it can't work *in
general*. *Stretching it out for general use turns those little cracks
into massive canyons. *A language needs a general mechanism that does
work - such as a polite cancellation API.
Neither *works in general* - polite cancellation *doesn't* work for
our us. That's my point - you probably want *both* for different use
cases. :-)

Yeah, but mine's less icky. ;)
But requires more code. :-)
I think the ideal for you would be a separate process. *I'd also
suggest a restricted VM only in a thread, but that probably wouldn't
work for those long-running .NET APIs. *Now, if those long-
running .NET APIs did polite cancellation, then you could combine that
with a restricted VM to get what you need.
No - we need to pull a large object graph *out* of the calculation
(with no guarantee that it is even serializable) and the overhead for
marshalling that puts using multiple processes out of the running.

What we *want* is what we've got! And it works very well... None of
the problems you predict. :-)

We may at a future date look to using AppDomains to sandbox user code
- but haven't needed to yet.

Michael
http://www.ironpythoninaction.com/
>
I think what bothers me is, even if those external APIs support polite
cancellation properly, your forced interruptions will bleed over and
mess them up. *There needs to be a way of containing it better.
Writing them in another language (as C is used for most of Python's
builtins today) isn't a reasonable requirement.
Jun 27 '08 #19

P: n/a
On Jun 11, 1:17 pm, Fuzzyman <fuzzy...@gmail.comwrote:
On Jun 11, 6:49 pm, Rhamphoryncus <rha...@gmail.comwrote:
On Jun 11, 7:56 am, Fuzzyman <fuzzy...@gmail.comwrote:
On Jun 11, 6:56 am, Rhamphoryncus <rha...@gmail.comwrote:
I'm not saying it can't be made to work in your specific case - it
likely does work well for you. I'm saying it can't work *in
general*. Stretching it out for general use turns those little cracks
into massive canyons. A language needs a general mechanism that does
work - such as a polite cancellation API.
Neither *works in general* - polite cancellation *doesn't* work for
our us. That's my point - you probably want *both* for different use
cases. :-)
Yeah, but mine's less icky. ;)

But requires more code. :-)
Both require significant support from the implementation, and you're
not the one volunteering to write it (I am). Besides, they're
complementary, so we should have both anyway. The question is how
best to fit them together.

I think the ideal for you would be a separate process. I'd also
suggest a restricted VM only in a thread, but that probably wouldn't
work for those long-running .NET APIs. Now, if those long-
running .NET APIs did polite cancellation, then you could combine that
with a restricted VM to get what you need.

No - we need to pull a large object graph *out* of the calculation
(with no guarantee that it is even serializable) and the overhead for
marshalling that puts using multiple processes out of the running.
Ouch. So if it fails you want it isolated and killed, but if it
succeeds you want to share it with the rest of the program.

What we *want* is what we've got! And it works very well... None of
the problems you predict. :-)
Which points to an unknown mechanism protecting the vulnerable code,
such as using a different language.

I think we've run out of material to discuss. We're about 80% in
agreement, with a 20% disagreement on philosophy.
Jun 27 '08 #20

P: n/a
On Jun 11, 8:41*pm, Rhamphoryncus <rha...@gmail.comwrote:
On Jun 11, 1:17 pm, Fuzzyman <fuzzy...@gmail.comwrote:
On Jun 11, 6:49 pm, Rhamphoryncus <rha...@gmail.comwrote:
On Jun 11, 7:56 am, Fuzzyman <fuzzy...@gmail.comwrote:
On Jun 11, 6:56 am, Rhamphoryncus <rha...@gmail.comwrote:
I'm not saying it can't be made to work in your specific case - it
likely does work well for you. *I'm saying it can't work *in
general*. *Stretching it out for general use turns those little cracks
into massive canyons. *A language needs a general mechanism thatdoes
work - such as a polite cancellation API.
Neither *works in general* - polite cancellation *doesn't* work for
our us. That's my point - you probably want *both* for different use
cases. :-)
Yeah, but mine's less icky. ;)
But requires more code. :-)

Both require significant support from the implementation, and you're
not the one volunteering to write it (I am). *Besides, they're
complementary, so we should have both anyway. *The question is how
best to fit them together.
I think the ideal for you would be a separate process. *I'd also
suggest a restricted VM only in a thread, but that probably wouldn't
work for those long-running .NET APIs. *Now, if those long-
running .NET APIs did polite cancellation, then you could combine that
with a restricted VM to get what you need.
No - we need to pull a large object graph *out* of the calculation
(with no guarantee that it is even serializable) and the overhead for
marshalling that puts using multiple processes out of the running.

Ouch. *So if it fails you want it isolated and killed, but if it
succeeds you want to share it with the rest of the program.
What we *want* is what we've got! And it works very well... None of
the problems you predict. :-)

Which points to an unknown mechanism protecting the vulnerable code,
such as using a different language.

I think we've run out of material to discuss. *We're about 80% in
agreement, with a 20% disagreement on philosophy.
:-)

Michael
Jun 27 '08 #21

This discussion thread is closed

Replies have been disabled for this discussion.