Skip to content

[Internal]: Fixes the Observed exception (ObjectDisposedException) in GlobalEndpointManager #5197

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 55 additions & 12 deletions Microsoft.Azure.Cosmos/src/Routing/GlobalEndpointManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,14 @@ private async Task GetAndUpdateAccountPropertiesAsync(Uri endpoint)
if (databaseAccount != null)
{
this.AccountProperties = databaseAccount;
this.CancellationTokenSource.Cancel();
try
{
this.CancellationTokenSource.Cancel();
}
catch (ObjectDisposedException)
{
// Ignore the exception if the cancellation token source is already disposed
}
}
}
catch (Exception e)
Expand All @@ -348,7 +355,14 @@ private async Task GetAndUpdateAccountPropertiesAsync(Uri endpoint)
if (GetAccountPropertiesHelper.IsNonRetriableException(e))
{
DefaultTrace.TraceInformation("GlobalEndpointManager: Exception is not retriable");
this.CancellationTokenSource.Cancel();
try
{
this.CancellationTokenSource.Cancel();
}
catch (ObjectDisposedException)
{
// Ignore the exception if the cancellation token source is already disposed
}
this.NonRetriableException = e;
}
else
Expand Down Expand Up @@ -405,15 +419,36 @@ private static IEnumerable<Uri> GetServiceEndpoints(
}
}
}

public void Dispose()
{
if (Interlocked.Increment(ref this.disposeCounter) == 1)
// Dispose of unmanaged resources.
this.Dispose(true);
// Suppress finalization.
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (Interlocked.Increment(ref this.disposeCounter) != 1)
{
this.CancellationTokenSource?.Cancel();
this.CancellationTokenSource?.Dispose();
return;
}

if (disposing)
{
try
{
this.CancellationTokenSource?.Cancel();
this.CancellationTokenSource?.Dispose();
}
catch (ObjectDisposedException)
{
// Ignore exceptions during dispose
}

}

}

}

public virtual Uri ResolveServiceEndpoint(DocumentServiceRequest request)
Expand Down Expand Up @@ -493,12 +528,20 @@ public void Dispose()
{
this.connectionPolicy.PreferenceChanged -= this.OnPreferenceChanged;
if (!this.cancellationTokenSource.IsCancellationRequested)
{
// This can cause task canceled exceptions if the user disposes of the object while awaiting an async call.
this.cancellationTokenSource.Cancel();
// The background timer task can hit a ObjectDisposedException but it's an async background task
// that is never awaited on so it will not be thrown back to the caller.
this.cancellationTokenSource.Dispose();
{
try
{
// This can cause task canceled exceptions if the user disposes of the object while awaiting an async call.
this.cancellationTokenSource.Cancel();
// The background timer task can hit a ObjectDisposedException but it's an async background task
// that is never awaited on so it will not be thrown back to the caller.
this.cancellationTokenSource.Dispose();
}
catch (ObjectDisposedException)
{
// Ignore the exception if the cancellation token source is already disposed

}
}
}

Expand Down
Loading