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
Disposewill 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.csto: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
SerialPortconstructor, 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.