What is so bad aboud Thread.stop() ?

T

taqmcg

The use of Thread.stop() is strongly deprecated, but I'm a bit confused by the explanation given in the documentation: (e.g., http://docs.oracle.com/javase/6/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html)

Because it is inherently unsafe. Stopping a thread causes
it to unlock all the monitors that it has locked. (The
monitors are unlocked as the ThreadDeath exception propagates
up the stack.) If any of the objects previously protected by
these monitors were in an inconsistent state, other threads
may now view these objects in an inconsistent state.
Such objects are said to be damaged. When threads operate on
damaged objects, arbitrary behavior can result. This behavior
may be subtle and difficult to detect, or it may be pronounced.
Unlike other unchecked exceptions, ThreadDeath kills threads silently;
thus, the user has no warning that his program may be corrupted.
The corruption can manifest itself at any time after the actual
damage occurs, even hours or days in the future.

As I understand this, the ThreadDeath exception is treated exactly as any other exception -- finally blocks are honored, it can even be caught -- thatmight be thrown unexpectedly. E.g., if we got an OutOfMemoryError or we happen to explicitly throw a RuntimeException we're going to see exactly the same behavior with monitors released progressively as we go up the stack.It's certainly easy enough to catch and rethrow the ThreadDeath in its run method
if I really want to log it and address the one difference.

So what is the big hullaballoo about? Is there something special going on here with Thread.stop(), or is this just a specific instance of the fact the we should be very careful whenever a thread has been stopped by an unexpected exception?

Thread.stop() might be called at any time in the to-be-stopped thread, and that might be an issue, but at least in principle the thread that issues the stop could check the to-be-stopped thread and only stop it at 'appropriate' points where appropriate is defined by the user.

E.g., suppose I have some concern that a piece of code that I'm about to run might have an infinite loop in it (say I'm testing somebody else's regular expression parser with lots of different RE's), but it's not going to allocate any external resources (e.g., files, DB connections). I could set/clear a flag as I enter and leave the suspect code. Could I safely monitor this thread in another thread. After say 100 seconds if a given expression hasn't parsed can the monitor thread invoke a Thread.stop() safely if my flag shows that the RE thread is caught in the parser?

Thanks for your insight.
Regards,
Tom MCglynn
 
M

Marcel Müller

The use of Thread.stop() is strongly deprecated, but I'm a bit confused by the explanation given in the documentation: (e.g., http://docs.oracle.com/javase/6/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html)

Do you know about race conditions in multi-threaded programming?
Thread.stop() can cause race conditions because it interrupts the thread
at any arbitrary location. So code that is executed under protection of
a mutex (=monitor) can be forced to release the mutex without a chance
to complete its work. This breaks the happens-before relation that the
mutex introduced.

Think of the following pseudo instruction sequence.

// interrupted thread
1. mutex.enter();
2. staticVar = new MyClass();
3. staticVar.setParent(some_parent_window);
4. mutex.exit();

// other thread
1. mutex.enter();
2. if (staticVar == null) continue at step 5
3. MyClass parent = staticVar.getParent();
4. do_somthing_with(parent);
5. mutex.exit();

This fragment is perfectly valid under normal conditions but it has a
race condition if the first thread can be stopped. If it happens that
the first thread is stopped after step 2 then the class referred by
staticVar might only be partially initialized, because Thread.stop
forces the execution of step 4 but not step 3. This causes the other
thread to fail badly because it may use a null reference at its step 4.

Indeed, strictly speaking the above code is not exception safe. I
setParent() throws the result is the same. But most real world code is
not exception safe (at any point). Simply because trivial functions like
getters usually don't throw. In Java most exceptions therefore can't be
thrown without declaration.
As I understand this, the ThreadDeath exception is treated exactly as any other exception -- finally blocks are honored, it can even be caught -- that might be thrown unexpectedly. E.g., if we got an OutOfMemoryError or we happen to explicitly throw a RuntimeException we're going to see exactly the same behavior with monitors released progressively as we go up the stack. It's certainly easy enough to catch and rethrow the ThreadDeath in its run method
if I really want to log it and address the one difference.

True, but no one expects a program to do anything reasonable after an
out of memory exception. Most likely Java does not reasonable recover
from that anyway, because subsequent new operators are likely to fail too.
E.g., suppose I have some concern that a piece of code that I'm about to run might have an infinite loop in it (say I'm testing somebody else's regular expression parser with lots of different RE's), but it's not going to allocate any external resources (e.g., files, DB connections). I could set/clear a flag as I enter and leave the suspect code. Could I safely monitor this thread in another thread. After say 100 seconds if a given expression hasn't parsed can the monitor thread invoke a Thread.stop() safely if my flag shows that the RE thread is caught in the parser?

You could do that under certain conditions.

First accessing any side effects of the interrupted code (like static
vars or modified objects) might result in undefined behavior. You might
ensure this in your case.

Secondly the executing code must not have spawned own threads e.g. for
using more than one CPU core. This cannot be more than a convention,
because you never know what the used libraries do behind the scenes.
E.g. calling an FFT-library might result in parallel threads. It may
also schedule the computing to the graphics hardware if the hardware and
the drivers are suitable for that.

So for testing purposes a separate task is significantly safer. Of
course, if you are testing your own code and you know what you are
doing, just use Thread.stop. Hey, it's just a test case, and if it
succeeds Thread.stop has never been called, so this result is reliable.
But further tests in the same run /might/ not be reliable anymore if you
aborted the test.


Marcel
 
A

Arne Vajhøj

The use of Thread.stop() is strongly deprecated, but I'm a bit confused by the explanation given in the documentation: (e.g., http://docs.oracle.com/javase/6/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html)

Because it is inherently unsafe. Stopping a thread causes
it to unlock all the monitors that it has locked. (The
monitors are unlocked as the ThreadDeath exception propagates
up the stack.) If any of the objects previously protected by
these monitors were in an inconsistent state, other threads
may now view these objects in an inconsistent state.
Such objects are said to be damaged. When threads operate on
damaged objects, arbitrary behavior can result. This behavior
may be subtle and difficult to detect, or it may be pronounced.
Unlike other unchecked exceptions, ThreadDeath kills threads silently;
thus, the user has no warning that his program may be corrupted.
The corruption can manifest itself at any time after the actual
damage occurs, even hours or days in the future.

As I understand this, the ThreadDeath exception is treated exactly as
any other exception -- finally blocks are honored, it can even be
caught -- that might be thrown unexpectedly. E.g., if we got an
OutOfMemoryError or we happen to explicitly throw a RuntimeException
we're going to see exactly the same behavior with monitors released
progressively as we go up the stack. It's certainly easy enough to
catch and rethrow the ThreadDeath in its run method if I really want
to log it and address the one difference.

So what is the big hullaballoo about? Is there something special
going on here with Thread.stop(), or is this just a specific instance
of the fact the we should be very careful whenever a thread has been
stopped by an unexpected exception?

Thread.stop() might be called at any time in the to-be-stopped
thread, and that might be an issue, but at least in principle the
thread that issues the stop could check the to-be-stopped thread and
only stop it at 'appropriate' points where appropriate is defined by
the user.

E.g., suppose I have some concern that a piece of code that I'm about
to run might have an infinite loop in it (say I'm testing somebody
else's regular expression parser with lots of different RE's), but
it's not going to allocate any external resources (e.g., files, DB
connections). I could set/clear a flag as I enter and leave the
suspect code. Could I safely monitor this thread in another thread.
After say 100 seconds if a given expression hasn't parsed can the
monitor thread invoke a Thread.stop() safely if my flag shows that
the RE thread is caught in the parser?

I think this part is the critical part

# If any of the objects previously protected by
# these monitors were in an inconsistent state, other threads
# may now view these objects in an inconsistent state.

There are cases where using it may result in problems.

There may also be cases where it will work fine. But that is
not sufficient to consider something "safe".

Go with the recommended approach of having the external
thread set a flag and the thread itself read it and close
down.

Arne
 
L

Lew

Do you know what they mean by a monitor?

Inconsistent state is bad.

Damaged is bad.

Arbitrary behavior is bad.

Subtle and difficult to detect is bad, really even worse than pronounced, because
it confounds one's ability to fix it.

Killed silently is bad.

No warning that the program is corrupted is bad.

Random timing of corruption is bad.

Except for the differences mentioned in the passage you cited.

Who said that 'Thread.stop()' release monitors progressively or goes up thestack?

Who will catch the exception?

Broken code that fails silently at unexpected times in ways that are difficult to detect,
let alone diagnose, that causes your program to be useless but you can't fix it.

Even if it were, it wouldn't merit the word "just".

No, because the starting thread has no insight into where the started thread is,
or what points are appropriate, except for critical sections, which are forshit when
a 'stop()' call destroys things.
No.

I think this part is the critical part

# If any of the objects previously protected by
# these monitors were in an inconsistent state, other threads
# may now view these objects in an inconsistent state.

There are cases where using it may result in problems.

There may also be cases where it will work fine. But that is
not sufficient to consider something "safe".

Go with the recommended approach of having the external
thread set a flag and the thread itself read it and close
down.

Buy and closely study _Java Concurrency in Practice_ by Brian Goetz, et al.You will
not get the in-depth understanding you need from a newsgroup.
 
K

Kevin McMurtrie

The use of Thread.stop() is strongly deprecated, but I'm a bit confused by
the explanation given in the documentation: (e.g.,
http://docs.oracle.com/javase/6/docs/technotes/guides/concurrency/threadPrimit
iveDeprecation.html)

Because it is inherently unsafe. Stopping a thread causes
it to unlock all the monitors that it has locked. (The
monitors are unlocked as the ThreadDeath exception propagates
up the stack.) If any of the objects previously protected by
these monitors were in an inconsistent state, other threads
may now view these objects in an inconsistent state.
Such objects are said to be damaged. When threads operate on
damaged objects, arbitrary behavior can result. This behavior
may be subtle and difficult to detect, or it may be pronounced.
Unlike other unchecked exceptions, ThreadDeath kills threads silently;
thus, the user has no warning that his program may be corrupted.
The corruption can manifest itself at any time after the actual
damage occurs, even hours or days in the future.

As I understand this, the ThreadDeath exception is treated exactly as any
other exception -- finally blocks are honored, it can even be caught -- that
might be thrown unexpectedly. E.g., if we got an OutOfMemoryError or we
happen to explicitly throw a RuntimeException we're going to see exactly the
same behavior with monitors released progressively as we go up the stack.
It's certainly easy enough to catch and rethrow the ThreadDeath in its run
method
if I really want to log it and address the one difference.

So what is the big hullaballoo about? Is there something special going on
here with Thread.stop(), or is this just a specific instance of the fact the
we should be very careful whenever a thread has been stopped by an unexpected
exception?

Thread.stop() might be called at any time in the to-be-stopped thread, and
that might be an issue, but at least in principle the thread that issues the
stop could check the to-be-stopped thread and only stop it at 'appropriate'
points where appropriate is defined by the user.

E.g., suppose I have some concern that a piece of code that I'm about to run
might have an infinite loop in it (say I'm testing somebody else's regular
expression parser with lots of different RE's), but it's not going to
allocate any external resources (e.g., files, DB connections). I could
set/clear a flag as I enter and leave the suspect code. Could I safely
monitor this thread in another thread. After say 100 seconds if a given
expression hasn't parsed can the monitor thread invoke a Thread.stop() safely
if my flag shows that the RE thread is caught in the parser?

Thanks for your insight.
Regards,
Tom MCglynn

The problem is that it causes an exception from code that can not throw
an exception. It corrupts the data in shared objects. Example:

if (thing == null)
throw new NullPointerException("thing must not be null");
data[++count]= thing;

This could be killed after incrementing 'count' but before assigning the
array element. Now you have a very illegal null element.
 
U

usvirtualobservatory

.
Except for the differences mentioned in the passage you cited.

That's the crux of my confusion. It is my understanding that the propagation
of the thread death is exactly the same as for any other exception. So
ThreadDeath behaves exactly as any other exception that might be triggered.
The only difference is that it can get triggered anywhere. None of the items
you have in litany of 'bad' things is different for other exceptions.
Who said that 'Thread.stop()' release monitors progressively or goes up the stack?

The text I quoted. So Oracle (nee Sun).
Who will catch the exception?
The code being stopped. E.g., I could have my
thread defined in a class Z like:

class Z implements Runnable {
public void run() {
try {
... code
} catch (ThreadDeath e) {
log(e);
throw e;
}
}
}
Broken code that fails silently at unexpected times in ways that are difficult to detect,

let alone diagnose, that causes your program to be useless but you can't fix it.






Yes.

What is it that is special?
No, because the starting thread has no insight into where the started thread is,

or what points are appropriate, except for critical sections, which are for shit when

a 'stop()' call destroys things.

But as the example shows its easy to arrange things so that the stopping
thread can know something. Until I actually call Thread.stop, all the normal mechanisms by which thread's communicate can be invoked. Does it have tobe fine grained in some way that can't be done using these? Why?

Why not? By hypothesis say there are no subthreads created, no files, no external connections. I can ensure that no objects created in the RE code thread are going to be accessed by the monitor thread or any other -- at least in the code I control. We're just going to throw them away. What is itthat will trip me up?

Buy and closely study _Java Concurrency in Practice_ by Brian Goetz, et al. You will

not get the in-depth understanding you need from a newsgroup.

Maybe, but the discussion in a newsgroup can be quite informative.

Thanks for you comments,
Tom
 
U

usvirtualobservatory

.
The problem is that it causes an exception from code that can not throw

an exception. It corrupts the data in shared objects. Example:



if (thing == null)

throw new NullPointerException("thing must not be null");

data[++count]= thing;



This could be killed after incrementing 'count' but before assigning the

array element. Now you have a very illegal null element.

[My apologies to Kevin who will not see this directly since I've only access
to GoogleGroups to post.]

While it's clear that one cannot continue on naively after issuing a Thread.stop(), the question I'm trying to understand is whether it's feasible insome conditions to do so reasonably safely. E.g., suppose I don't look atany of the objects that are create/modified in the stopped thread. They are all thrown away. Then the fact that they are potentially in a damaged state need not be an issue -- they will never be used again.


But is there any system level magic that precludes doing this regardless ofthe care one takes? E.g., maybe there are lots of internal globals in seemingly innocuous standard classes that get corrupted that are impossible toavoid, or there's an unavoidable chance that garbage collection will be broken, or ???

Or is it that in practice it's difficult to do this with sufficient care, but is in principle achievable?

Regards,
Tom
 
A

Arne Vajhøj

The problem is that it causes an exception from code that can not throw
an exception. It corrupts the data in shared objects. Example:

if (thing == null)
throw new NullPointerException("thing must not be null");
data[++count]= thing;

This could be killed after incrementing 'count' but before assigning the

array element. Now you have a very illegal null element.
While it's clear that one cannot continue on naively after issuing a
Thread.stop(), the question I'm trying to understand is whether it's
feasible in some conditions to do so reasonably safely. E.g.,
suppose I don't look at any of the objects that are create/modified
in the stopped thread. They are all thrown away. Then the fact that
they are potentially in a damaged state need not be an issue -- they
will never be used again.

But is there any system level magic that precludes doing this
regardless of the care one takes? E.g., maybe there are lots of
internal globals in seemingly innocuous standard classes that get
corrupted that are impossible to avoid, or there's an unavoidable
chance that garbage collection will be broken, or ???

Or is it that in practice it's difficult to do this with sufficient
care, but is in principle achievable?

I think it is something like:

You can achieve what you want to do in two ways:
A) use Thread.stop
B) set a flag and let the thread do what it need to do to
terminate in a graceful manner

#A can be done safely in some cases and can not be done safely in
other cases. Even if it can be done safely, then it will require
significant analysis to get it right. And even if it gets done
right, then there is a high risk that that a bug will be introduced
during maintenance later, because the maintenance programmer do not
have the skill or the time to understand the subtleties of the
problem.

#B can always be done safely. It requires not much work. And
is relative maintenance friendly.

Easy choice in my opinion.

Arne
 
S

Sven Köhler

The use of Thread.stop() is strongly deprecated, but I'm a bit
confused by the explanation given in the documentation: (e.g.,
http://docs.oracle.com/javase/6/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html)

Because it is inherently unsafe. Stopping a thread causes it to
unlock all the monitors that it has locked. (The monitors are
unlocked as the ThreadDeath exception propagates up the stack.) If
any of the objects previously protected by these monitors were in an
inconsistent state, other threads may now view these objects in an
inconsistent state. Such objects are said to be damaged. When threads
operate on damaged objects, arbitrary behavior can result. This
behavior may be subtle and difficult to detect, or it may be
pronounced. Unlike other unchecked exceptions, ThreadDeath kills
threads silently; thus, the user has no warning that his program may
be corrupted. The corruption can manifest itself at any time after
the actual damage occurs, even hours or days in the future.

As I understand this, the ThreadDeath exception is treated exactly as
any other exception -- finally blocks are honored, it can even be
caught -- that might be thrown unexpectedly.

A method that aquires a monitor usually performs a complex task.
Consider the removal of an element from a double-linked list for
example. A method deleting an element would first aquire the monitor,
then manipulate a few references, at least two. And that is simply not
atomic. If the ThreadDeath exception is thrown after the first reference
has been adjusted but before the second reference has been adjusted,
then the integrity of the list is broken. You wouldn't want that to
happen, would you? The result can be arbitrary behaviour when this list
is subquently used.

I have not seen anybody coding in a such way, that he anticipated a
ThreadDeath exception in every line of a synchronized block. In
particular, I never saw the finally block that would be needed to
restore the integrity of the list (or whatever object the method is
working on) in case of such an exception. And I would argue, that it's
very tricky to do too!
E.g., if we got an
OutOfMemoryError or we happen to explicitly throw a RuntimeException
we're going to see exactly the same behavior with monitors released
progressively as we go up the stack. It's certainly easy enough to
catch and rethrow the ThreadDeath in its run method if I really want
to log it and address the one difference.

I would assume, that an OutOfMemoryError thrown in the wrong line can
actually result in an object's integrity being broken as well. Have you
ever programmed in such a way, that the integrity of any object will not
be harmed by an unexpected OutOfMemoryError? Or are you, like anybody
else, praying that it never happens?



Regards,
Sven
 
E

Eric Sosman

[...]
I think it is something like:

You can achieve what you want to do in two ways:
A) use Thread.stop
B) set a flag and let the thread do what it need to do to
terminate in a graceful manner

#A can be done safely in some cases and can not be done safely in
other cases. Even if it can be done safely, then it will require
significant analysis to get it right. And even if it gets done
right, then there is a high risk that that a bug will be introduced
during maintenance later, because the maintenance programmer do not
have the skill or the time to understand the subtleties of the
problem.

#B can always be done safely. It requires not much work. And
is relative maintenance friendly.

The O.P.'s use case involved third-party "suspect code" that
might dive into an infinite loop somewhere unexpected. I think
that rules out #B because you might overlook the fatal loop while
salting "should I stop now?" tests throughout the code (you might
not even have the freedom to insert tests). I'd say the "suspect"
nature of the code also rules out #A, if #A is possible at all
(I'm not convinced it is).

There's a #C, though: Run the suspect code in its own JVM, as
a separate process. If it goes silent for a long time, kill the
entire process. You don't need to worry about the integrity of a
JVM that's no longer living, and any corruption inside the dead
process' address space won't contaminate your own.
 
T

taqmcg

On 8/1/2013 11:00 AM, (e-mail address removed) wrote:

I think it is something like:



You can achieve what you want to do in two ways:
A) use Thread.stop
B) set a flag and let the thread do what it need to do to
terminate in a graceful manner


#A can be done safely in some cases and can not be done safely in
other cases. Even if it can be done safely, then it will require
significant analysis to get it right. And even if it gets done
right, then there is a high risk that that a bug will be introduced
during maintenance later, because the maintenance programmer do not
have the skill or the time to understand the subtleties of the
problem.



#B can always be done safely. It requires not much work. And
is relative maintenance friendly.

Easy choice in my opinion.

Arne

Sure... If you control all the code, and your code has no bugs in it (so that no infinite loop occurs somewhere you didn't expect). That's not always the case -- I certainly expect that my code has bugs and I use a fair number of external libraries which may have bugs of there own.

Since most of my task code is single threaded and numerical, and I'd plan on throwing away anything touched by a killed thread, a lot of the concerns that are brought up seem more handleable than might be the case in other applications.

Tom
 
M

markspace

Sure... If you control all the code, and your code has no bugs in it
(so that no infinite loop occurs somewhere you didn't expect).
That's not always the case -- I certainly expect that my code has
bugs and I use a fair number of external libraries which may have
bugs of there own.


Well, the better option is to use a library without major bugs that
require Thread.stop(). Numerical libraries are fairly common, can you
find one that doesn't hang?

Another better option is to use Thread.interrupt(). That's a flag
defined for you in the system and checked often by many system
libraries. It's a clean way of stopping a thread.

Another better option is to decompile the library code (not hard for
byte code, somewhat hard for machine code) and insert a check for
Thread.interrupt() or some other flag or condition, so that you don't
need to use Thread.stop().

But yes it's possible to use Thread.stop() in extremis. I wouldn't
though. Use System.exit() instead, if things have really gone that far
off the rails. Better to cleanly shutdown the JVM than risk weird bugs
or whatnot. However, see the "find a less buggy library" option up top.
 
L

Lew

The code being stopped. E.g., I could have my
thread defined in a class Z like:

class Z implements Runnable {
public void run() {
try {
... code
} catch (ThreadDeath e) {

Since this catch is in the same thread that just died, it cannot run.
 
S

Steven Simpson

Since this catch is in the same thread that just died, it cannot run.

Are you saying that this won't print out "Dead"?

public class Stopped {
public static void main(String[] args) throws Exception {
Thread t = new Thread() {
public void run() {
try {
Thread.sleep(10000);
} catch (InterruptedException ex) {
System.out.println("Interrupted");
} catch (ThreadDeath td) {
System.out.println("Dead");
}
}
};

t.start();
Thread.sleep(4000);
System.out.println("Stopping");
t.stop();
}
}

I get:

Stopping
Dead
 
T

taqmcg

(e-mail address removed) wrote:
Since this catch is in the same thread that just died, it cannot run.

Are you saying that this won't print out "Dead"?

public class Stopped {
public static void main(String[] args) throws Exception {
Thread t = new Thread() {
public void run() {
try {
Thread.sleep(10000);
} catch (InterruptedException ex) {
System.out.println("Interrupted");
} catch (ThreadDeath td) {
System.out.println("Dead");
}
}
};

t.start();
Thread.sleep(4000);
System.out.println("Stopping");
t.stop();
}
}

I get:

Stopping
Dead


It's interesting that even one as well versed in Java as Lew seems to misunderstand how Thread.stop works. An (admittedly non-authoritative) explanation is available at http://vanillajava.blogspot.com/2011/06/threadstop-really-stop-thread.html. I think Lew shares the apprehension I had had that itdoes something magical and brings the thread down instantly, it seems clear that its behavior is dangerous but bounded.


Tom
 
T

taqmcg

The use of Thread.stop() is strongly deprecated, but I'm a bit confused
by the explanation given in the documentation: (e.g.,
[...]
So what is the big hullaballoo about?


I suspect (modulo my other suspicion that you can't rely on exactly what
Thread.stop() actually does in an actual implementation) that /if/ there is no
mutable state shared with the rest of the program, then it might be OK.
Problem is: there's not a lot of point in a thread that shares /no/ statewith
the rest of the program. If it's doing some computation (your? example of an
untrusted regexp engine for instance) then it has to get the answer back to the
calling thread somehow, and that is problematic. Maybe there are some simple
(in the sense of unsophisticated) mechanisms -- the calling thread polling a
volatile variable perhaps (though I have doubts about the semantics of that:
does reading a volatile variable guarantee that the data /referenced/ by that
variable are consistent ? My reading of the JLS doesn't find an answer to that
question). But, say, stop()-ing a thread that is writing to a shared queue is a
no-no.

I don't think you need to do anything particularly dramatic or even necessarily unusual to make separate out the thread-that-may-be-stopped's objects from the general ruck. E.g., while the thread is running it works only on objects it creates. Only when it finishes successfully does the monitor thread use its results. If the thread fails, they are just tossed out. I don't think there is a problem with the stoppable thread having readonly access to data shared with the monitor. You might get some kind of deadlock issue, but that's just general multithreading. Should it have a lock on a shared object when it is killed, then if it has only readonly access, it won'tbe leaving the locked object in a damaged state when the monitor is released. [AFAICT]
/If/ you know that the thread is in a fixed, stable, state then you can
probably kill it (assuming the state is suitable), but what about the
end-points -- just as it is entering or leaving that state. I find it
difficult to imagine how you could be sure, avoiding race conditions, that it
would be safe to stop() the thread unless your architecture was already such
that implementing an alternative method wouldn't be easier (or at least, no
harder -- and easier to justify to your peers ;-)

Does the thread need to be fixed or stable? I <think> I only need to have it isolated. That's part of what I'm trying to find out. And unless and until I kill it, I can communicate with it using any standard method for interthread communication (e.g., shared objects). That is much more difficultwere I using a separate JVM as some have suggested.

You mention elsewhere that you're concerned that Thread.stop() might be only partially or imperfectly implemented. That would certainly be an issue. That would be the kind of 'magical' issue that a programmer simply can't get around. However the documentation I've seen suggests that it is the danger of the method, not the quality of the implementation that is an issue.

In any case, it certainly seems like the deprecation has done its job of keeping people from trying it out!

Regards,
Tom
 
A

Arne Vajhøj

[...]
I think it is something like:

You can achieve what you want to do in two ways:
A) use Thread.stop
B) set a flag and let the thread do what it need to do to
terminate in a graceful manner

#A can be done safely in some cases and can not be done safely in
other cases. Even if it can be done safely, then it will require
significant analysis to get it right. And even if it gets done
right, then there is a high risk that that a bug will be introduced
during maintenance later, because the maintenance programmer do not
have the skill or the time to understand the subtleties of the
problem.

#B can always be done safely. It requires not much work. And
is relative maintenance friendly.

The O.P.'s use case involved third-party "suspect code" that
might dive into an infinite loop somewhere unexpected. I think
that rules out #B because you might overlook the fatal loop while
salting "should I stop now?" tests throughout the code (you might
not even have the freedom to insert tests). I'd say the "suspect"
nature of the code also rules out #A, if #A is possible at all
(I'm not convinced it is).

There's a #C, though: Run the suspect code in its own JVM, as
a separate process. If it goes silent for a long time, kill the
entire process. You don't need to worry about the integrity of a
JVM that's no longer living, and any corruption inside the dead
process' address space won't contaminate your own.

Not being able to change the code that needs to be interrupted
is a difficult case.

#C may be the only option for that case.

Arne
 
A

Arne Vajhøj

Sure... If you control all the code, and your code has no bugs in it
(so that no infinite loop occurs somewhere you didn't expect).
That's not always the case -- I certainly expect that my code has
bugs and I use a fair number of external libraries which may have
bugs of there own.

They assume that you control the code.

They do not assume that there are no unexpected bugs. They just
don't handle the unexpected bugs.
Since most of my task code is single threaded and numerical, and I'd
plan on throwing away anything touched by a killed thread, a lot of
the concerns that are brought up seem more handleable than might be
the case in other applications.

And you may get it to work.

But why spend more time on a worse solution?

Arne
 
A

Arne Vajhøj

It's interesting that even one as well versed in Java as Lew seems to
misunderstand how Thread.stop works. An (admittedly
non-authoritative) explanation is available at
http://vanillajava.blogspot.com/2011/06/threadstop-really-stop-thread.html.
I think Lew shares the apprehension I had had that it does something
magical and brings the thread down instantly, it seems clear that its
behavior is dangerous but bounded.

Lew is an experienced programmer.

He would never waste hours investigating something that is
known to be a bad solution from the beginning.

Arne
 
A

Arne Vajhøj

In any case, it certainly seems like the deprecation has done its job
of keeping people from trying it out!

True.

People are also discarding assembler for their web application without
actually trying it out.

Most developers get paid to solve a business problem. If there is a
simple fast way of doing that and a unknown risky way, then you pick
the simple fast way every time and move on. They do not get paid to
spend a lot of time researching why, how much and in what cases
something is bad.

Arne
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top