Bug #110789 OpenAsync throws unhandled exception from thread pool
Submitted: 24 Apr 2023 18:17 Modified: 7 Jun 2023 14:59
Reporter: Bradley Grainger (OCA) Email Updates:
Status: Verified Impact on me:
None 
Category:Connector / NET Severity:S2 (Serious)
Version:8.0.33, 8.3.0 OS:Windows (10)
Assigned to: CPU Architecture:Any

[24 Apr 2023 18:17] Bradley Grainger
Description:
If MySqlConnection.OpenAsync throws a timeout exception, it's now thrown from a background threadpool thread and cannot be handled by the application. This can crash the whole process.

With MySql.Data 8.0.32.1, the test program prints the following output (and exits successfully)

Caught MySql.Data.MySqlClient.MySqlException in 00:00:02.1639965
OpenAsync finished in 00:00:02.1655379

With MySql.Data 8.0.33, the test program crashes with an unhandled exception:

Unhandled exception. System.AggregateException: One or more errors occurred. (Timeout expired.  The timeout period elapsed prior to 
completion of the operation or the server is not responding.)
 ---> MySql.Data.MySqlClient.MySqlException (0x80004005): Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.
 ---> System.TimeoutException: The operation has timed out.
   at MySql.Data.Common.StreamCreator.<>c.<GetTcpStreamAsync>b__8_1()
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)      
--- End of stack trace from previous location ---
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)      
   at System.Threading.CancellationTokenSource.ExecuteCallbackHandlers(Boolean throwOnFirstException)
   --- End of inner exception stack trace ---
   at System.Threading.CancellationTokenSource.ExecuteCallbackHandlers(Boolean throwOnFirstException)
   at System.Threading.TimerQueueTimer.Fire(Boolean isThreadPool)
   at System.Threading.TimerQueue.FireNextTimers()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()

It's expected that OpenAsync will return a Task that eventually becomes faulted, so that the application can "await" it and observe the exception.

How to repeat:
Create a "dotnet new console" program and add the following code:

static async Task Main(string[] args)
{
	using var connection = new MySqlConnection("server=www.mysql.com;Connect Timeout=2");
	var stopwatch = Stopwatch.StartNew();
	try
	{
		await connection.OpenAsync();
	}
	catch (Exception ex)
	{
		Console.WriteLine($"Caught {ex.GetType()} in {stopwatch.Elapsed}");
	}
	Console.WriteLine($"OpenAsync finished in {stopwatch.Elapsed}");
}
[7 Jun 2023 14:59] MySQL Verification Team
Hello Bradley Grainger,

Thank you for the bug report.
Verified as described.

Regards,
Ashwini Patil
[4 Mar 9:50] MySQL Verification Team
Bug #114065 marked as duplicate of this one.
[10 Mar 21:32] Ryousuke Tanida
Hello.

As reported in Bug #114065, it seems that a similar issue has occurred.
Currently, a timeout occurs when pausing due to debugging, so proper development is not possible with the current version.
When will this bug be fixed?

Also, could you please give me some advice on how to work around this issue?

We welcome your feedback.