stop() boundaries

J

Jan Burse

Dear All

Suppose I have the following code:

A; /* line 1 */
try { /* line 2 */
B; /* line 3 */
} finally {
C;
}

Now I run this in a thread and arbitrarily
call the deprecated (sic!) stop() once.

Would it be possible that the stop will
throw a thread death error on line 2,
thus after A has been executed and before
the try block is entered?

Bye
 
J

Jan Burse

Patricia said:
You have to assume that the exception can be thrown anywhere, because it
is documented to be thrown "almost anywhere", and, as far as I know,
there is no documentation guaranteeing that it won't happen in any
particular place. In your case, I see nothing special about statement A
that would prevent a ThreadDeath before, during, or immediately after A.

Usually try/catch/finally blocks disappear somehow in the
compiled code, and are replaced by a lookup table. So I guess
it is not possible to abort the thread at line 2. Either we
are inside the try block and in front of B, or outside of the
try block and in front of A, or inside A. Or somewhere else.

But I am not sure about this hypothesis. It would be a clarification
of the "almost anywhere", and would be an interesting invariant of
stop().

Bye
 
K

Kevin McMurtrie

Jan Burse said:
Dear All

Suppose I have the following code:

A; /* line 1 */
try { /* line 2 */
B; /* line 3 */
} finally {
C;
}

Now I run this in a thread and arbitrarily
call the deprecated (sic!) stop() once.

Would it be possible that the stop will
throw a thread death error on line 2,
thus after A has been executed and before
the try block is entered?

Bye

Line 2 produces an exception table, not code. Line 3 may be wrapped
with some code for the finally block. Execution of 'C' may be aborted
by stop(), and that's why stop() is no longer supported.

You can use Thread interrupts to abort non-blocking code by polling
Thread.interrupted() or Thread.isInterrupted() and manually throwing
InterruptedException. You can also poll a volatile boolean field.
 
L

Lew

Dear All

Suppose I have the following code:

A; /* line 1 */
try { /* line 2 */
B; /* line 3 */
} finally {
C;
}

Now I run this in a thread and arbitrarily
call the deprecated (sic!) stop() once.

Yes, they do call it "deprecated", and it is that in both the English and the
Java sense.

http://download.oracle.com/javase/6/docs/api/java/lang/Thread.html#stop()
*Deprecated.*
This method is inherently unsafe. Stopping a thread with Thread.stop
causes it to unlock all of the monitors that it has locked (as a
natural consequence of the unchecked ThreadDeath exception propagating
up the stack). If any of the objects previously protected by these
monitors were in an inconsistent state, the damaged objects become
visible to other threads, potentially resulting in arbitrary behavior.

"This method is inherently unsafe."
For more information, see Why are Thread.stop, Thread.suspend
and Thread.resume Deprecated?.
http://download.oracle.com/javase/6...s/concurrency/threadPrimitiveDeprecation.html
Why is Thread.stop deprecated?
Because it is inherently unsafe. ....
Unlike other unchecked exceptions, ThreadDeath kills threads silently;
thus, the user has no warning that his program may be corrupted.

"... it is inherently unsafe."

"Inherently" is a pretty strong word.

What are you trying to accomplish?
 
J

Jan Burse

Lew said:
"... it is inherently unsafe."

"Inherently" is a pretty strong word.

What are you trying to accomplish?

Proper use of java.util.concurrent in the same sense
as synchronized works.

They also say in the documentation that ThreadDeath will
unravel synchronized statements. So under the hood they
must have some boundaries and some finally blocks.

So when I use the native monitors, I will have what
stop() boundaries here?

A;
synchronized (obj) {
B;
}
C;


Assume I am now using something like:

A;
ReentrantLock lock=new ReentrantLock();
lock.lock();
try {
B;
} finally {
lock.unlock()
}
C;

Will it *always* unravel my lock when using stop()?
Under the assumption that B does not throw any exception
except when it gets a ThreadDeath injected.

Is it possible that a ThreadDeath is injected after
lock.lock() and before try, so that lock.unlock() is
not called?

Bye
 
L

Lew

That's part of what I'm looking for. Now for the rest of my curiosity, WHY
are you investigating 'stop()' in particular? You do know that you aren't
supposed to use it at all, ever, right? So why 'stop()'?

What exactly does "proper use of java.util.concurrent" have to do with
'stop()'? I see no connection whatsoever, other than that the former obviates
the latter.

Patricia said:
Remember that stop is deprecated because it is inherently unsafe. I
don't think you are going to be able to base anything "proper" on such a
shaky foundation.

The flag-and-interrupt approach provides a much more solid foundation.

Patricia said:
You seem to be thinking of lock.lock() as an atomic unit that cannot be
partly executed before a stop. Is that right? If so, do you have any
basis for that assumption? I don't see anything in the relevant code
that would prevent a stop and ThreadDeath.

If that assumption is not justified, you need to consider cases such as
the stop hitting with the return from lock.lock() as the next statement.
The lock is locked, but control has not returned to your code, and
execution is still outside your try-finally block. Even worse, the stop
may hit in the middle of ReentrantLock.Sync.nonfairTryAcquire(), leaving
the lock in an inconsistent state.

I believe this sort of issue lead to the recognition that stop() could
not be used safely, and the decision get rid of the problem by
deprecating it.

In other words, "DO NOT EVER USE 'Thread#stop()'!"
 
K

Kevin McMurtrie

Jan Burse said:
Proper use of java.util.concurrent in the same sense
as synchronized works.

They also say in the documentation that ThreadDeath will
unravel synchronized statements. So under the hood they
must have some boundaries and some finally blocks.

So when I use the native monitors, I will have what
stop() boundaries here?

A;
synchronized (obj) {
B;
}
C;


Assume I am now using something like:

A;
ReentrantLock lock=new ReentrantLock();
lock.lock();
try {
B;
} finally {
lock.unlock()
}
C;

Will it *always* unravel my lock when using stop()?

No. lock.unlock() can be called normally then aborted by a call to
stop().

More importantly, protecting B with a lock implies that it is modifying
shared data in a non-atomic manner. That implies that aborting it in an
undeclared location would leave damaged shared data behind.
 
M

Mike Schilling

Jan Burse said:
Proper use of java.util.concurrent in the same sense
as synchronized works.

If the question is "How do I protect use of concurrent classes against
clients calling stop()?", I'm fairly sure the answer is "You can't".
 
D

Daniel Pitts

Proper use of java.util.concurrent in the same sense
as synchronized works.

They also say in the documentation that ThreadDeath will
unravel synchronized statements. So under the hood they
must have some boundaries and some finally blocks.

So when I use the native monitors, I will have what
stop() boundaries here?

A;
synchronized (obj) {
B;
}
C;


Assume I am now using something like:

A;
ReentrantLock lock=new ReentrantLock();
lock.lock();
try {
B;
} finally {
lock.unlock()
}
C;

Will it *always* unravel my lock when using stop()?
Under the assumption that B does not throw any exception
except when it gets a ThreadDeath injected.
It is possible that stop() causes the exception to be thrown just before
"lock.unlock" is executed, but after B has executed. So, your "finally"
may be bypassed. Oops.

Even worse, it could be that your lock is *half* unlocked, because it
isn't expecting to be interrupted in the middle of its operation, but
Thread.stop() does just that.

So, just don't do it. There are good reasons its been deprecated.
 

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

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top