Description
The simple code below works on all versions of .NET before 6.0, but crashes with "Unhandled exception. System.ObjectDisposedException: Safe handle has been closed." on net6.0:
using System;
using System.Net;
using System.Net.Sockets;
namespace Net60SafeHandleBug
{
class Program
{
static void Main(string[] args)
{
int port = 1234;
IPAddress.TryParse("127.0.0.1", out IPAddress ipAddress);
Socket socket = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
IAsyncResult asyncResult = socket.BeginConnect(ipAddress, port, null, null);
// do something, then suddenly quit...
socket.Close();
asyncResult.AsyncWaitHandle.Close(); // <-- ruh roh
Console.WriteLine("Press any key to quit...");
Console.ReadKey();
}
}
}
Reproduction Steps
Build the above code as a console app. It will crash when targeting net6.0, but work fine with any older version of .NET.
Expected behavior
The application should succeed. The documentation for IAsyncResult.AsyncWaitHandle does not mention that one must wait for the handle to be signaled or call the APM End* method before closing, but it does say that the handle should be closed when the application is done using it.
Actual behavior
The application crashes with the following:
System.ObjectDisposedException
HResult=0x80131622
Message=Safe handle has been closed.
Object name: 'SafeHandle'.
Source=System.Private.CoreLib
StackTrace:
at System.Runtime.InteropServices.SafeHandle.DangerousAddRef(Boolean& success)
at Interop.Kernel32.SetEvent(SafeWaitHandle handle)
at System.Threading.EventWaitHandle.Set()
at System.Threading.ManualResetEventSlim.Set(Boolean duringCancellation)
at System.Threading.Tasks.Task.FinishStageTwo()
at System.Threading.Tasks.Task.FinishSlow(Boolean userDelegateExecute)
at System.Threading.Tasks.Task.TrySetException(Object exceptionObject)
at System.Threading.Tasks.ValueTask.ValueTaskSourceAsTask.<>c.<.cctor>b__4_0(Object state)
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.InvokeContinuation(Action`1 continuation, Object state, Boolean forceAsync, Boolean requiresExecutionContextFlow)
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.OnCompleted(SocketAsyncEventArgs _)
at System.Net.Sockets.SocketAsyncEventArgs.OnCompletedInternal()
at System.Net.Sockets.SocketAsyncEventArgs.HandleCompletionPortCallbackError(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
at System.Net.Sockets.SocketAsyncEventArgs.<>c.<.cctor>b__179_0(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
at System.Threading.ThreadPoolBoundHandleOverlapped.CompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pNativeOverlapped)
Regression?
This is a regression in .NET 6.0, because it works in all the prior versions.
Known Workarounds
No response
Configuration
Tested on net461, netcoreapp2.0, net5.0, and net6.0 running on Windows 10 (x64). Did not test on other platforms.
Other information
No response
Description
The simple code below works on all versions of .NET before 6.0, but crashes with "Unhandled exception. System.ObjectDisposedException: Safe handle has been closed." on net6.0:
Reproduction Steps
Build the above code as a console app. It will crash when targeting net6.0, but work fine with any older version of .NET.
Expected behavior
The application should succeed. The documentation for IAsyncResult.AsyncWaitHandle does not mention that one must wait for the handle to be signaled or call the APM End* method before closing, but it does say that the handle should be closed when the application is done using it.
Actual behavior
The application crashes with the following:
Regression?
This is a regression in .NET 6.0, because it works in all the prior versions.
Known Workarounds
No response
Configuration
Tested on net461, netcoreapp2.0, net5.0, and net6.0 running on Windows 10 (x64). Did not test on other platforms.
Other information
No response