Bug 25850

Summary: SafeHandle.Close() is not idempotent.
Product: [Mono] Class Libraries Reporter: Jonathan Pryor <jonp>
Component: mscorlibAssignee: Marek Safar <masafa>
Status: RESOLVED FIXED    
Severity: normal CC: masafa, mono-bugs+mono
Priority: ---    
Version: master   
Target Milestone: Untriaged   
Hardware: PC   
OS: Mac OS   
Tags: Is this bug a regression?: ---
Last known good build:

Description Jonathan Pryor 2015-01-08 17:55:12 UTC
Common practice and design guidelines is that IDisposable.Dispose()/Close()/etc. methods can be called multiple times on a method, and shouldn't throw an ObjectDisposedException.

Mono's SafeHandle implementation doesn't do that:

  using System;
  using System.Runtime.InteropServices;

  class MySafeHandle : SafeHandle {

    public MySafeHandle ()
      : base (IntPtr.Zero, ownsHandle:false)
    {
    }

    protected override bool ReleaseHandle ()
    {
      return true;
    }

    public override bool IsInvalid {
      get {return base.handle == IntPtr.Zero;}
    }
  }

  class App {
    public static void Main ()
    {
      var h = new MySafeHandle ();
      h.Close ();
      h.Close ();
    }
  }

Expected results: what .NET does: no output.

Actual results: an unhandled exception!

> System.ObjectDisposedException: The object was used after being disposed.
>   at System.Runtime.InteropServices.SafeHandle.Close () [0x0008d] in /private/tmp/source-mono-mac-3.12.0-branch-32/bockbuild-mono-3.12.0-branch/profiles/mono-mac-xamarin/build-root/mono-3.12.0/mcs/class/corlib/System.Runtime.InteropServices/SafeHandle.cs:107 
>   at App.Main () [0x0000e] in /Users/jon/tmp/csharp/sh.cs:28
Comment 1 Marek Safar 2015-01-12 08:05:51 UTC
Fixed in master