none
Thread abort after Monitor.Enter RRS feed

  • Question

  • Hi,
    I have a question and am trying to find a useful doc/reference on it. In C#, I have the following code:

    Monitor.Enter(lockObject);
    try {
     // do stuff
    } finally {
     Monitor.Exit(lockObject);
    }

    I am wondering what will happen if the thread that calls this piece of code gets aborted right after when it finishes calling Monitor.Enter(lockObject)?

    Will the lock be held forever? Will it leak any memory? Are there any other side effects? 
    Friday, May 2, 2008 4:33 AM

Answers

  • Finally blocks are guaranteed to run in case of Thread.Abort.  In .NET 1.x there used to be cases where if the finally block was executing in the middle of an abort, then it might have been aborted.  This is no longer the case under CLR 2.0.

    Friday, May 2, 2008 8:54 AM
  • For reference, here is the explanation from the MSDN documentation:

     

    http://msdn.microsoft.com/en-us/library/system.threading.thread.abort.aspx

     

    When a thread calls Abort on itself, the effect is similar to throwing an exception; the ThreadAbortException happens immediately, and the result is predictable. However, if one thread calls Abort on another thread, the abort interrupts whatever code is running. There is also a chance that a static constructor could be aborted. In rare cases, this might prevent instances of that class from being created in that application domain. In the .NET Framework versions 1.0 and 1.1, there is a chance the thread could abort while a finally block is running, in which case the finally block is aborted.

    Sunday, May 4, 2008 12:52 AM
  • Actually, the JIT guarantees that if the Monitor.Enter occurs immediately before the try block, then the thread wouldn't be aborted there.  The following article explains that: http://www.bluebytesoftware.com/blog/PermaLink,guid,d9ff204a-a8a5-400e-bcbc-dedb90a7d11a.aspx

    Monday, May 5, 2008 7:46 AM

All replies

  • Finally blocks are guaranteed to run in case of Thread.Abort.  In .NET 1.x there used to be cases where if the finally block was executing in the middle of an abort, then it might have been aborted.  This is no longer the case under CLR 2.0.

    Friday, May 2, 2008 8:54 AM
  • For reference, here is the explanation from the MSDN documentation:

     

    http://msdn.microsoft.com/en-us/library/system.threading.thread.abort.aspx

     

    When a thread calls Abort on itself, the effect is similar to throwing an exception; the ThreadAbortException happens immediately, and the result is predictable. However, if one thread calls Abort on another thread, the abort interrupts whatever code is running. There is also a chance that a static constructor could be aborted. In rare cases, this might prevent instances of that class from being created in that application domain. In the .NET Framework versions 1.0 and 1.1, there is a chance the thread could abort while a finally block is running, in which case the finally block is aborted.

    Sunday, May 4, 2008 12:52 AM
  • Hi Shasha,
    I understand that finally block is executed in case of Thread.Abort, but it will only execute if the execution has been inside of a "try/catch" block. If the execution has not reached there, how will the finally block execute?

    Consider the same example below:

    Monitor.Enter(lockObject);
    // here the Thread.Abort is called after the above statement executes....note that we have not yet entered try/catch block...

    try {
     // here is the code...if thread is aborted here, we are guaranteed to have the finally block run....
    } finally {
     Monitor.Exit(lockObject);
    }


    Please read the comments and let me know what do you think?
    Monday, May 5, 2008 3:52 AM
  • The case you depict could easily be prevented by moving the Monitor.Enter call into the try block!?
    Monday, May 5, 2008 7:13 AM
  • Actually, the JIT guarantees that if the Monitor.Enter occurs immediately before the try block, then the thread wouldn't be aborted there.  The following article explains that: http://www.bluebytesoftware.com/blog/PermaLink,guid,d9ff204a-a8a5-400e-bcbc-dedb90a7d11a.aspx

    Monday, May 5, 2008 7:46 AM
  • It is possible to get orphaned locks when compiling under 64 bit. More infos can be found at Joe Duffy´s blog.

    The problem is that the JIT compiler emits nop instructions in debug mode to enable the insertion of break points (int 3 call) after every instruction.

    Apart from this minor issue which already has been addressed:

    Update 4/17/08: This was indeed fixed for the X64 JIT in Visual Studio 2008.  Note that when compiling C# code targeting both X86 and X64, if you do not use the /o+ switch, this problem can still occur due to extra explicit NOPs inserted before the try.

     

    there is no way to get an orphaned lock if you hardware does work as specified.

     

    Yours,

       Alois Kraus

     

    Monday, May 5, 2008 8:12 PM
  • Per the article you linked to, the JIT compiler does not always guarantee that behaviour, it's a dangerous assumption, particularly in 64 bit.
    Monday, May 5, 2008 8:17 PM
  • Per the article, in the debug build it is possible for NOPs to be injected in the dangerous window (both in CLR 2.0 and the SP1 build).  In the release build of CLR 2.0 the 32-bit behavior is fine, the 64-bit isn't.  In the release build of SP1 both 32-bit and 64-bit behaviors are fine.

    One way or another, the best piece of advice to offer for cases like these is simply to refrain from rudely aborting threads if possible.
    Tuesday, May 6, 2008 1:03 PM