runtime: Dispose should not throw PlatformNotSupportedException even when the type is not supported
As reported by @ayende in a blog post, some types throw PlatformNotSupportedException
from Dispose(bool disposing)
on platforms that are not supported. This is problematic, because:
-
The big issue: The finalizer of a base class of some of those types (like
Component
) callsDispose(false)
, which causes the process to crash. -
The smaller issue: It’s against the Framework Design Guidelines:
X AVOID throwing an exception from within
Dispose(bool)
except under critical situations where the containing process has been corrupted (leaks, inconsistent shared state, etc.).Users expect that a call to
Dispose
will not raise an exception.I think this applies even for types that are not supported.
The original example was SqlConnection
, but I think a simpler repro is with SerialPort
, which is not supported on .Net Core on Linux:
-
The following should apply to any Linux machine with .Net Core installed (in my case, Ubuntu 16.04 and .Net Core SDK 2.0.3).
-
dotnet new console
-
dotnet add package System.IO.Ports
-
Change
Program.cs
to:using System; using System.IO.Ports; class Program { static void Main() { try { new SerialPort(); } catch (Exception ex) { Console.WriteLine(ex); } // to simulate GC and subsequent finalization at some point in the future GC.Collect(); GC.WaitForPendingFinalizers(); } }
-
Run it in Release mode (to make sure the finalizer is run):
dotnet run -c Release
-
The program first correctly catches the exception thrown from the
SerialPort
constructor, but then it crashes:System.PlatformNotSupportedException: System.IO.Ports is currently only supported on Windows. at System.IO.Ports.SerialPort..ctor() at Program.Main() in /home/osboxes/hwapp/Program.cs:line 10 Unhandled Exception: System.PlatformNotSupportedException: System.IO.Ports is currently only supported on Windows. at System.IO.Ports.SerialPort.Dispose(Boolean disposing) at System.ComponentModel.Component.Finalize()
I think that for unsupported types, Dispose
should be empty. It should not throw, to avoid crash that cannot be prevented (and to follow Framework Design Guidelines).
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Reactions: 8
- Comments: 15 (14 by maintainers)
Or just put in a no op line of code.