@@ -377,35 +377,45 @@ private async ValueTask<ServerSession> CreateSessionAsync(IOBehavior? ioBehavior
377
377
m_connectionSettings = pool ? . ConnectionSettings ?? new ConnectionSettings ( new MySqlConnectionStringBuilder ( m_connectionString ) ) ;
378
378
var actualIOBehavior = ioBehavior ?? ( m_connectionSettings . ForceSynchronous ? IOBehavior . Synchronous : IOBehavior . Asynchronous ) ;
379
379
380
- var connectTimeout = m_connectionSettings . ConnectionTimeout == 0 ? Timeout . InfiniteTimeSpan : TimeSpan . FromMilliseconds ( m_connectionSettings . ConnectionTimeoutMilliseconds ) ;
381
- using ( var timeoutSource = new CancellationTokenSource ( connectTimeout ) )
382
- using ( var linkedSource = CancellationTokenSource . CreateLinkedTokenSource ( cancellationToken , timeoutSource . Token ) )
380
+ CancellationTokenSource timeoutSource = null ;
381
+ CancellationTokenSource linkedSource = null ;
382
+ try
383
383
{
384
- try
384
+ // the cancellation token for connection is controlled by 'cancellationToken' (if it can be cancelled), ConnectionTimeout
385
+ // (from the connection string, if non-zero), or a combination of both
386
+ if ( m_connectionSettings . ConnectionTimeout != 0 )
387
+ timeoutSource = new CancellationTokenSource ( TimeSpan . FromMilliseconds ( m_connectionSettings . ConnectionTimeoutMilliseconds ) ) ;
388
+ if ( cancellationToken . CanBeCanceled && timeoutSource != null )
389
+ linkedSource = CancellationTokenSource . CreateLinkedTokenSource ( cancellationToken , timeoutSource . Token ) ;
390
+ var connectToken = linkedSource ? . Token ?? timeoutSource ? . Token ?? cancellationToken ;
391
+
392
+ // get existing session from the pool if possible
393
+ if ( pool != null )
385
394
{
386
- // get existing session from the pool if possible
387
- if ( pool != null )
388
- {
389
- // this returns an open session
390
- return await pool . GetSessionAsync ( this , actualIOBehavior , linkedSource . Token ) . ConfigureAwait ( false ) ;
391
- }
392
- else
393
- {
394
- // only "fail over" and "random" load balancers supported without connection pooling
395
- var loadBalancer = m_connectionSettings . LoadBalance == MySqlLoadBalance . Random && m_connectionSettings . HostNames . Count > 1 ?
396
- RandomLoadBalancer . Instance : FailOverLoadBalancer . Instance ;
397
-
398
- var session = new ServerSession ( ) ;
399
- Log . Info ( "Created new non-pooled Session{0}" , session . Id ) ;
400
- await session . ConnectAsync ( m_connectionSettings , loadBalancer , actualIOBehavior , linkedSource . Token ) . ConfigureAwait ( false ) ;
401
- return session ;
402
- }
395
+ // this returns an open session
396
+ return await pool . GetSessionAsync ( this , actualIOBehavior , connectToken ) . ConfigureAwait ( false ) ;
403
397
}
404
- catch ( OperationCanceledException ex ) when ( timeoutSource . IsCancellationRequested )
398
+ else
405
399
{
406
- throw new MySqlException ( "Connect Timeout expired." , ex ) ;
400
+ // only "fail over" and "random" load balancers supported without connection pooling
401
+ var loadBalancer = m_connectionSettings . LoadBalance == MySqlLoadBalance . Random && m_connectionSettings . HostNames . Count > 1 ?
402
+ RandomLoadBalancer . Instance : FailOverLoadBalancer . Instance ;
403
+
404
+ var session = new ServerSession ( ) ;
405
+ Log . Info ( "Created new non-pooled Session{0}" , session . Id ) ;
406
+ await session . ConnectAsync ( m_connectionSettings , loadBalancer , actualIOBehavior , connectToken ) . ConfigureAwait ( false ) ;
407
+ return session ;
407
408
}
408
409
}
410
+ catch ( OperationCanceledException ex ) when ( timeoutSource . IsCancellationRequested )
411
+ {
412
+ throw new MySqlException ( "Connect Timeout expired." , ex ) ;
413
+ }
414
+ finally
415
+ {
416
+ linkedSource ? . Dispose ( ) ;
417
+ timeoutSource ? . Dispose ( ) ;
418
+ }
409
419
}
410
420
411
421
internal bool SslIsEncrypted => m_session . SslIsEncrypted ;
@@ -422,7 +432,12 @@ internal void SetState(ConnectionState newState)
422
432
{
423
433
var previousState = m_connectionState ;
424
434
m_connectionState = newState ;
425
- OnStateChange ( new StateChangeEventArgs ( previousState , newState ) ) ;
435
+ var eventArgs =
436
+ previousState == ConnectionState . Closed && newState == ConnectionState . Connecting ? s_stateChangeClosedConnecting :
437
+ previousState == ConnectionState . Connecting && newState == ConnectionState . Open ? s_stateChangeConnectingOpen :
438
+ previousState == ConnectionState . Open && newState == ConnectionState . Closed ? s_stateChangeOpenClosed :
439
+ new StateChangeEventArgs ( previousState , newState ) ;
440
+ OnStateChange ( eventArgs ) ;
426
441
}
427
442
}
428
443
@@ -487,6 +502,9 @@ private ConnectionSettings GetConnectionSettings()
487
502
}
488
503
489
504
static readonly IMySqlConnectorLogger Log = MySqlConnectorLogManager . CreateLogger ( nameof ( MySqlConnection ) ) ;
505
+ static readonly StateChangeEventArgs s_stateChangeClosedConnecting = new StateChangeEventArgs ( ConnectionState . Closed , ConnectionState . Connecting ) ;
506
+ static readonly StateChangeEventArgs s_stateChangeConnectingOpen = new StateChangeEventArgs ( ConnectionState . Connecting , ConnectionState . Open ) ;
507
+ static readonly StateChangeEventArgs s_stateChangeOpenClosed = new StateChangeEventArgs ( ConnectionState . Open , ConnectionState . Closed ) ;
490
508
491
509
string m_connectionString ;
492
510
ConnectionSettings m_connectionSettings ;
0 commit comments