none
SafeHandle and Thread.Sleep(500); RRS feed

  • Question

  • In this article
    http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.safehandle.aspx

    in the constructor the author creates a SafeHandle does a Thread.Sleep(500) and then assigns the new handle to another SaveHandle.

                MySafeFileHandle tmpHandle;
                tmpHandle = NativeMethods.CreateFile(fileName, NativeMethods.GENERIC_READ,
                    FileShare.Read, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero);

                // An async exception here will cause us to run our finalizer with
                // a null _handle, but MySafeFileHandle's ReleaseHandle code will
                // be invoked to free the handle.

                // This call to Sleep, run from the fault injection code in Main,
                // will help trigger a race. But it will not cause a handle leak
                // because the handle is already stored in a SafeHandle instance.
                // Critical finalization then guarantees that freeing the handle,
                // even during an unexpected AppDomain unload.
                Thread.Sleep(500);
                _handle = tmpHandle;  // Makes _handle point to a critical finalizable object.


    I don't understand what this is all about. It is a very long wait and what does the assignment accomplish.

    Thanks.
    Tom

     


    Tom G.
    Monday, January 31, 2011 6:29 PM

Answers

  • The code snippet you posted here is actually executed in a separate thread (let's call it thread B), other than the thread executing the Main method (call it thread A), thread B sleep for 500ms, just waiting for thread A to terminate it:

     

                        Thread t = new Thread(new ParameterizedThreadStart(ViewInHex));

                        t.Start(fileName);

                        Thread.Sleep(1);

                        while (!_workerStarted)

                        {

                            Thread.Sleep(0);

                        }

                        t.Abort();  // Normal applications should not do this.

    Usually, there will be a handle leak, because thread B is aborted before it gets an opportunity to assign newly created file handle to its private field (private MySafeFileHandle _handle), but the underlying OS file handle has been created; even though the MyFileReader object will be disposed, its _handle field is still null, thus a handle leak might occurs.

    But, notice that the MySafeFileHandle class is derived from SafeHandleZeroOrMinusOneIsInvalid:

    internal class MySafeFileHandle : SafeHandleZeroOrMinusOneIsInvalid

    So, for following statement:

                MySafeFileHandle tmpHandle;

                tmpHandle = NativeMethods.CreateFile(fileName, NativeMethods.GENERIC_READ,

                    FileShare.Read, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero);

    After an unmanaged handle was created, the marshaler will construct a MySafeFileHandle object, store the unmanaged handle in the MySafeFileHandle object, and pass the MySafeFileHandle object to managed world. When thread B is aborted, the ReleaseHandle method of MySafeFileHandle object: tmpHandle will be invoked to realse unmanaged handle, so the handle leak is avoided.


    Eric Yang [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • Marked as answer by Tom Groszko Tuesday, February 1, 2011 6:22 PM
    Tuesday, February 1, 2011 8:56 AM

All replies

  • The code snippet you posted here is actually executed in a separate thread (let's call it thread B), other than the thread executing the Main method (call it thread A), thread B sleep for 500ms, just waiting for thread A to terminate it:

     

                        Thread t = new Thread(new ParameterizedThreadStart(ViewInHex));

                        t.Start(fileName);

                        Thread.Sleep(1);

                        while (!_workerStarted)

                        {

                            Thread.Sleep(0);

                        }

                        t.Abort();  // Normal applications should not do this.

    Usually, there will be a handle leak, because thread B is aborted before it gets an opportunity to assign newly created file handle to its private field (private MySafeFileHandle _handle), but the underlying OS file handle has been created; even though the MyFileReader object will be disposed, its _handle field is still null, thus a handle leak might occurs.

    But, notice that the MySafeFileHandle class is derived from SafeHandleZeroOrMinusOneIsInvalid:

    internal class MySafeFileHandle : SafeHandleZeroOrMinusOneIsInvalid

    So, for following statement:

                MySafeFileHandle tmpHandle;

                tmpHandle = NativeMethods.CreateFile(fileName, NativeMethods.GENERIC_READ,

                    FileShare.Read, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero);

    After an unmanaged handle was created, the marshaler will construct a MySafeFileHandle object, store the unmanaged handle in the MySafeFileHandle object, and pass the MySafeFileHandle object to managed world. When thread B is aborted, the ReleaseHandle method of MySafeFileHandle object: tmpHandle will be invoked to realse unmanaged handle, so the handle leak is avoided.


    Eric Yang [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • Marked as answer by Tom Groszko Tuesday, February 1, 2011 6:22 PM
    Tuesday, February 1, 2011 8:56 AM
  • Thanks for your answer. Good explanation.

     

     


    Tom G.
    Tuesday, February 1, 2011 6:22 PM