What is so bad aboud Thread.stop() ?

Discussion in 'Java' started by taqmcg@gmail.com, Jul 31, 2013.

  1. Guest

    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
     
    , Jul 31, 2013
    #1
    1. Advertising

  2. On 31.07.13 15.36, wrote:
    > 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
     
    Marcel Müller, Jul 31, 2013
    #2
    1. Advertising

  3. Arne Vajhøj Guest

    On 7/31/2013 9:36 AM, wrote:
    > 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
     
    Arne Vajhøj, Jul 31, 2013
    #3
  4. Lew Guest

    Arne Vajhøj wrote:
    > wrote:
    >> 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


    Do you know what they mean by a monitor?

    >> 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


    Inconsistent state is bad.

    >> may now view these objects in an inconsistent state.
    >> Such objects are said to be damaged. When threads operate on


    Damaged is bad.

    >> damaged objects, arbitrary behavior can result. This behavior


    Arbitrary behavior is bad.

    > > may be subtle and difficult to detect, or it may be pronounced.


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

    >> Unlike other unchecked exceptions, ThreadDeath kills threads silently;


    Killed silently is bad.

    >> thus, the user has no warning that his program may be corrupted.


    No warning that the program is corrupted is bad.

    >> The corruption can manifest itself at any time after the actual
    >> damage occurs, even hours or days in the future.


    Random timing of corruption is bad.

    >> As I understand this, the ThreadDeath exception is treated exactly as
    >> any other exception -- finally blocks are honored, it can even be


    Except for the differences mentioned in the passage you cited.

    >> 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


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

    >> catch and rethrow the ThreadDeath in its run method if I really want
    >> to log it and address the one difference.


    Who will catch the exception?

    >> So what is the big hullaballoo about? Is there something special


    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.

    >> going on here with Thread.stop(), or is this just a specific instance


    Yes.

    >> of the fact the we should be very careful whenever a thread has been
    >> stopped by an unexpected exception?


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

    >> 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.


    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.

    >> 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?


    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.

    --
    Lew
     
    Lew, Jul 31, 2013
    #4
  5. In article <>,
    wrote:

    > 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.
    --
    I will not see posts from Google because I must filter them as spam
     
    Kevin McMurtrie, Aug 1, 2013
    #5
  6. Guest

    On Wednesday, July 31, 2013 5:13:25 PM UTC-4, Lew wrote:
    ....
    > >> As I understand this, the ThreadDeath exception is treated exactly as

    >
    > >> any other exception -- finally blocks are honored, it can even be

    >
    >
    >
    > 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.
    >
    >
    > >> 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

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


    The text I quoted. So Oracle (nee Sun).

    >
    >
    >
    > >> catch and rethrow the ThreadDeath in its run method if I really want

    >
    > >> to log it and address the one difference.

    >
    >
    >
    > 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;
    }
    }
    }
    >
    >
    > >> So what is the big hullaballoo about? Is there something special

    >
    >
    >
    > 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.
    >
    >
    >
    > >> going on here with Thread.stop(), or is this just a specific instance

    >
    >
    >
    > Yes.


    What is it that is special?
    >
    >
    >
    > >> 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.

    >
    >
    >
    > 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?

    >
    >
    >
    > >> 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?

    >
    >
    >
    > No.


    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?


    >
    >
    >
    > > 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.
    >
    >
    >
    > --
    >
    > Lew


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

    Thanks for you comments,
    Tom
     
    , Aug 1, 2013
    #6
  7. Guest

    On Thursday, August 1, 2013 12:09:20 AM UTC-4, Kevin McMurtrie wrote:
    ....
    > 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.
    >
    > --
    >
    > I will not see posts from Google because I must filter them as spam


    [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
     
    , Aug 1, 2013
    #7
  8. Arne Vajhøj Guest

    On 8/1/2013 11:00 AM, wrote:
    > On Thursday, August 1, 2013 12:09:20 AM UTC-4, Kevin McMurtrie wrote:
    > ...
    >> 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
     
    Arne Vajhøj, Aug 1, 2013
    #8
  9. Sven Köhler Guest

    On 31/07/13 16:36, wrote:
    > 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
     
    Sven Köhler, Aug 1, 2013
    #9
  10. Eric Sosman Guest

    On 8/1/2013 11:25 AM, Arne Vajhøj 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.


    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.

    --
    Eric Sosman
    d
     
    Eric Sosman, Aug 1, 2013
    #10
  11. Guest

    On Thursday, August 1, 2013 11:25:25 AM UTC-4, Arne Vajhøj wrote:
    > On 8/1/2013 11:00 AM, 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
     
    , Aug 1, 2013
    #11
  12. markspace Guest

    On 8/1/2013 9:30 AM, wrote:

    > 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.
     
    markspace, Aug 1, 2013
    #12
  13. Lew Guest

    wrote:
    > Lew wrote:
    >> 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) {


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

    > log(e);
    > throw e;
    > }
    > }
    > }


    --
    Lew
     
    Lew, Aug 1, 2013
    #13
  14. On 01/08/13 22:07, Lew wrote:
    > wrote:
    >> Lew wrote:
    >>> 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) {

    > 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



    --
    ss at comp dot lancs dot ac dot uk
     
    Steven Simpson, Aug 1, 2013
    #14
  15. Guest

    On Thursday, August 1, 2013 6:15:23 PM UTC-4, Steven Simpson wrote:
    > On 01/08/13 22:07, Lew wrote:
    >
    > > wrote:

    >
    > >> Lew wrote:
    > >>> 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) {

    > > 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
     
    , Aug 2, 2013
    #15
  16. Guest

    On Friday, August 2, 2013 1:50:02 PM UTC-4, Chris Uppal wrote:
    > wrote:
    >
    > > 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
     
    , Aug 2, 2013
    #16
  17. Arne Vajhøj Guest

    On 8/1/2013 11:49 AM, Eric Sosman wrote:
    > On 8/1/2013 11:25 AM, Arne Vajhøj 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.

    >
    > 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
     
    Arne Vajhøj, Aug 3, 2013
    #17
  18. Arne Vajhøj Guest

    On 8/1/2013 12:30 PM, wrote:
    > On Thursday, August 1, 2013 11:25:25 AM UTC-4, Arne Vajhøj wrote:
    >> On 8/1/2013 11:00 AM, 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.

    >
    > 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
     
    Arne Vajhøj, Aug 3, 2013
    #18
  19. Arne Vajhøj Guest

    On 8/1/2013 7:16 PM, wrote:
    > On Thursday, August 1, 2013 6:15:23 PM UTC-4, Steven Simpson wrote:
    >> On 01/08/13 22:07, Lew wrote:
    >>> wrote:
    >>>> Lew wrote:
    >>>>> 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) {
    >>> Since this catch is in the same thread that just died, it cannot
    >>> run.

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

    ....
    >> 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 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
     
    Arne Vajhøj, Aug 3, 2013
    #19
  20. Arne Vajhøj Guest

    On 8/2/2013 2:34 PM, wrote:
    > 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
     
    Arne Vajhøj, Aug 3, 2013
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Matt Theule

    Stop Debugging doesn't stop in ASP.NET

    Matt Theule, Jul 23, 2003, in forum: ASP .Net
    Replies:
    7
    Views:
    753
    Matt Theule
    Jul 24, 2003
  2. Son KwonNam
    Replies:
    11
    Views:
    2,622
    mr_organic
    Apr 9, 2004
  3. Will
    Replies:
    1
    Views:
    15,331
    Thomas Weidenfeller
    Nov 2, 2004
  4. Benji
    Replies:
    34
    Views:
    1,200
    pkriens
    Oct 28, 2005
  5. rantingrick
    Replies:
    44
    Views:
    1,250
    Peter Pearson
    Jul 13, 2010
Loading...

Share This Page