From 27b847077bffc131b1f7612b4073e6655d161776 Mon Sep 17 00:00:00 2001 From: ComputerMaster1st Date: Sun, 24 Jun 2018 00:18:14 +0100 Subject: [PATCH 1/5] Fixed AudioClient Disconnect Deadlock --- src/Discord.Net.WebSocket/ConnectionManager.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/Discord.Net.WebSocket/ConnectionManager.cs b/src/Discord.Net.WebSocket/ConnectionManager.cs index decae4163..53feae1b4 100644 --- a/src/Discord.Net.WebSocket/ConnectionManager.cs +++ b/src/Discord.Net.WebSocket/ConnectionManager.cs @@ -106,9 +106,7 @@ namespace Discord public virtual async Task StopAsync() { Cancel(); - var task = _task; - if (task != null) - await task.ConfigureAwait(false); + await Task.CompletedTask; } private async Task ConnectAsync(CancellationTokenSource reconnectCancelToken) @@ -159,9 +157,9 @@ namespace Discord await _onDisconnecting(ex).ConfigureAwait(false); - await _logger.InfoAsync("Disconnected").ConfigureAwait(false); - State = ConnectionState.Disconnected; await _disconnectedEvent.InvokeAsync(ex, isReconnecting).ConfigureAwait(false); + State = ConnectionState.Disconnected; + await _logger.InfoAsync("Disconnected").ConfigureAwait(false); } public async Task CompleteAsync() From 9d1d03e46a09be2d557a6ef022bac0181176adb1 Mon Sep 17 00:00:00 2001 From: ComputerMaster1st Date: Mon, 25 Jun 2018 20:08:51 +0100 Subject: [PATCH 2/5] RunAsync now catches UdpClient ObjectDisposedException & breaks --- .../Net/DefaultUdpSocket.cs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/Discord.Net.WebSocket/Net/DefaultUdpSocket.cs b/src/Discord.Net.WebSocket/Net/DefaultUdpSocket.cs index 251a761d4..cdf485fd2 100644 --- a/src/Discord.Net.WebSocket/Net/DefaultUdpSocket.cs +++ b/src/Discord.Net.WebSocket/Net/DefaultUdpSocket.cs @@ -113,16 +113,20 @@ namespace Discord.Net.Udp private async Task RunAsync(CancellationToken cancelToken) { - var closeTask = Task.Delay(-1, cancelToken); while (!cancelToken.IsCancellationRequested) { - var receiveTask = _udp.ReceiveAsync(); - var task = await Task.WhenAny(closeTask, receiveTask).ConfigureAwait(false); - if (task == closeTask) - break; + try + { + var result = await _udp.ReceiveAsync() + .ConfigureAwait(false); - var result = receiveTask.Result; - await ReceivedDatagram(result.Buffer, 0, result.Buffer.Length).ConfigureAwait(false); + await ReceivedDatagram(result.Buffer, 0, result.Buffer.Length).ConfigureAwait(false); + } + catch (ObjectDisposedException) + { + //if we get this the UDP socket has been closed (by dispose, so it has been cancelled) + break; + } } } } From 47c458aa61f6463bddfbe4277d911dc24b7b3055 Mon Sep 17 00:00:00 2001 From: ComputerMaster1st Date: Tue, 26 Jun 2018 11:11:36 +0100 Subject: [PATCH 3/5] Reverted to previous implementation & now using continuewith instead --- .../Net/DefaultUdpSocket.cs | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/Discord.Net.WebSocket/Net/DefaultUdpSocket.cs b/src/Discord.Net.WebSocket/Net/DefaultUdpSocket.cs index cdf485fd2..e92b31b8d 100644 --- a/src/Discord.Net.WebSocket/Net/DefaultUdpSocket.cs +++ b/src/Discord.Net.WebSocket/Net/DefaultUdpSocket.cs @@ -113,20 +113,26 @@ namespace Discord.Net.Udp private async Task RunAsync(CancellationToken cancelToken) { + var closeTask = Task.Delay(-1, cancelToken); while (!cancelToken.IsCancellationRequested) { - try - { - var result = await _udp.ReceiveAsync() - .ConfigureAwait(false); + var receiveTask = _udp.ReceiveAsync(); - await ReceivedDatagram(result.Buffer, 0, result.Buffer.Length).ConfigureAwait(false); - } - catch (ObjectDisposedException) +#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed + receiveTask.ContinueWith((recieveResult) => { - //if we get this the UDP socket has been closed (by dispose, so it has been cancelled) + //observe the exception as to not recieve as unhandled exception + _ = recieveResult.Exception; + + }, TaskContinuationOptions.OnlyOnFaulted); +#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed + + var task = await Task.WhenAny(closeTask, receiveTask).ConfigureAwait(false); + if (task == closeTask) break; - } + + var result = receiveTask.Result; + await ReceivedDatagram(result.Buffer, 0, result.Buffer.Length).ConfigureAwait(false); } } } From 6cc23a065330eb835073865bfb07280c780d1316 Mon Sep 17 00:00:00 2001 From: ComputerMaster1st Date: Tue, 24 Jul 2018 14:30:19 +0100 Subject: [PATCH 4/5] Minor Changes Requested By Foxbot --- src/Discord.Net.WebSocket/ConnectionManager.cs | 4 ++-- src/Discord.Net.WebSocket/Net/DefaultUdpSocket.cs | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/Discord.Net.WebSocket/ConnectionManager.cs b/src/Discord.Net.WebSocket/ConnectionManager.cs index 53feae1b4..65adc1583 100644 --- a/src/Discord.Net.WebSocket/ConnectionManager.cs +++ b/src/Discord.Net.WebSocket/ConnectionManager.cs @@ -103,10 +103,10 @@ namespace Discord finally { _stateLock.Release(); } }); } - public virtual async Task StopAsync() + public virtual Task StopAsync() { Cancel(); - await Task.CompletedTask; + return Task.CompletedTask; } private async Task ConnectAsync(CancellationTokenSource reconnectCancelToken) diff --git a/src/Discord.Net.WebSocket/Net/DefaultUdpSocket.cs b/src/Discord.Net.WebSocket/Net/DefaultUdpSocket.cs index e92b31b8d..c8496807e 100644 --- a/src/Discord.Net.WebSocket/Net/DefaultUdpSocket.cs +++ b/src/Discord.Net.WebSocket/Net/DefaultUdpSocket.cs @@ -118,14 +118,12 @@ namespace Discord.Net.Udp { var receiveTask = _udp.ReceiveAsync(); -#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed - receiveTask.ContinueWith((recieveResult) => + _ = receiveTask.ContinueWith((recieveResult) => { //observe the exception as to not recieve as unhandled exception _ = recieveResult.Exception; }, TaskContinuationOptions.OnlyOnFaulted); -#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed var task = await Task.WhenAny(closeTask, receiveTask).ConfigureAwait(false); if (task == closeTask) From 4286324508c642b8cfe6b60f99ba93da7ad02665 Mon Sep 17 00:00:00 2001 From: ComputerMaster1st Date: Mon, 27 Aug 2018 14:22:02 +0100 Subject: [PATCH 5/5] Disconnecting block fix --- src/Discord.Net.WebSocket/DiscordSocketClient.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Discord.Net.WebSocket/DiscordSocketClient.cs b/src/Discord.Net.WebSocket/DiscordSocketClient.cs index 793d2b29c..c51ece23b 100644 --- a/src/Discord.Net.WebSocket/DiscordSocketClient.cs +++ b/src/Discord.Net.WebSocket/DiscordSocketClient.cs @@ -207,7 +207,8 @@ namespace Discord.WebSocket await heartbeatTask.ConfigureAwait(false); _heartbeatTask = null; - while (_heartbeatTimes.TryDequeue(out long time)) { } + // Check if hearbeatTimes is not empty before dequeuing. TryDequeue can cause blocking. + if (!_heartbeatTimes.IsEmpty) while (_heartbeatTimes.TryDequeue(out long time)) { } _lastMessageTime = 0; await _gatewayLogger.DebugAsync("Waiting for guild downloader").ConfigureAwait(false);