[concurrency-interest] Does "Thread.stop" do what is says it does?

Dawid Kurzyniec dawidk at mathcs.emory.edu
Fri Aug 5 14:28:30 EDT 2005


Ian Griffiths wrote:

>It seems to me that this discussion still leaves unanswered the central
>question:
>
>- How can we stop a thread that has got out of control (infinite looping
>or other anti-social behavior)?
>  
>
As Josh said, nothing is really foolproof, since a malicious thread can 
always catch and ignore ThreadDeath. In fact, some months ago I was 
experiencing JVM crashes when simulating such malicious service and 
attempts of the system to aggressively get rid of it. But, if it is safe 
to assume that the code is not malicious, but that it can be just buggy 
(e.g. frequent pattern: try { ... } catch (InterruptedException e) {}), 
with careful class loader confinement, I think Thread.stop is the best 
solution we have now. Before stopping, it is probably a good idea to 
apply the procedure described in CPJ book: ask nicely, then interrupt, 
then revoke security privileges and lower priority.

The best solution I can come up with to the problem of Thread.stop being 
no-op if the thread has not yet been started, is to check isAlive, and 
if false, precede stop() with start() (catching possible exception). 
Thread references should be kept in a weak data structure, so that 
unreferenced threads are ignored and gc-ed even if they have not yet 
started. This way, when we see a non-collected thread that is not alive, 
we know that somebody probably holds a reference to it and may be 
planning something nasty, so it is safer to defensively start/stop.

Also, a non-trivial problem here is to decide which threads should 
actually be terminated, since, in general, the mapping between services 
(or sessions) and threads is dynamic. Our system 
(http://www.mathcs.emory.edu/dcl/h2o/) permits external remote 
invocations of hosted services. When an RMI thread enters the service 
code, it becomes subject to termination if the service is destroyed, but 
it is no longer so after it exits the service code. When a thread 
"attached" to a service spawns a new thread, that new thread should also 
be "attached" to the service. Implementing this seems impossible at 
first sight, but it can be done with a bit of trickery, intercepting 
setPriority() from the thread constructor in a security manager. 
Finally, tasks submitted to thread pools by a thread "attached" to a 
service should usually also be attached to that service. To achieve 
that, we have implemented a thread local delegation mechanism, and a 
simple security-extended version of ThreadPoolExecutor, which delegates 
context class loader, access control context, and delegatable thread 
locals from the submitter to the task. As long as all "shared" thread 
pools are instances of this class, the service-to-threads association is 
correctly preserved.

In addition to service-to-threads association, we needed 
session-to-threads association: when the user session is terminated, all 
threads associated with that session should be terminated. This can be 
implemented in an analogous way as service-to-threads association.

Regards,
Dawid



More information about the Concurrency-interest mailing list