Longer workaround delay, additional logging

This commit is contained in:
Dominion
2023-06-03 01:37:05 -04:00
parent 34a7e58bd4
commit 7fd744f9dc
@@ -234,23 +234,34 @@ namespace Tgstation.Server.Host.Components.Chat.Providers
// https://github.com/Remora/Remora.Discord/issues/305
var responderDispatchService = serviceProvider.GetRequiredService<ResponderDispatchService>();
var serviceProviderDisposeTask = serviceProvider.DisposeAsync().AsTask();
var timeout = AsyncDelayer.Delay(TimeSpan.FromSeconds(5), default); // DCT: None available
var timeout = AsyncDelayer.Delay(TimeSpan.FromSeconds(10), default); // DCT: None available
await Task.WhenAny(timeout, serviceProviderDisposeTask);
if (!serviceProviderDisposeTask.IsCompleted)
{
// HACK HACK HACK, there's a potential deadlock in the ResponderDispatchService
Logger.LogWarning("ServiceProvider disposal stalled. Attempting workaround...");
var responderDispatchServiceType = responderDispatchService.GetType();
var dispatcherTask = (Task)responderDispatchServiceType.GetField("_dispatcher", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(responderDispatchService);
var finalizerTask = (Task)responderDispatchServiceType.GetField("_finalizer", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(responderDispatchService);
if (dispatcherTask.IsCompleted && !finalizerTask.IsCompleted)
var dispatcherCompleted = dispatcherTask.IsCompleted;
var finalizerCompleted = finalizerTask.IsCompleted;
if (dispatcherCompleted && !finalizerCompleted)
{
// deadlocked, force close the channel
var channel = (Channel<Task<IReadOnlyList<Result>>>)responderDispatchServiceType.GetField("_respondersToFinalize", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(responderDispatchService);
channel.Writer.TryComplete();
if (!channel.Writer.TryComplete())
Logger.LogCritical("Workaround failed (channel already closed), you may be deadlocked!");
else
Logger.LogInformation("Workaround seems successful. Awaiting ServiceProvider disposal...");
}
else
Logger.LogCritical(
"Workaround failed (_dispatcher: {dispatcherCompleted}, _finalizer: {finalizerCompleted}), you may be deadlocked!",
dispatcherCompleted,
finalizerCompleted);
}
await serviceProviderDisposeTask;