From 27b847077bffc131b1f7612b4073e6655d161776 Mon Sep 17 00:00:00 2001 From: ComputerMaster1st Date: Sun, 24 Jun 2018 00:18:14 +0100 Subject: [PATCH 1/8] 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/8] 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/8] 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/8] 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/8] 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); From 4407b9b8c058dee0327ad2f31c4098086c1e2852 Mon Sep 17 00:00:00 2001 From: ComputerMaster1st Date: Tue, 4 Sep 2018 11:59:39 +0100 Subject: [PATCH 6/8] Added msg.content null check --- src/Discord.Net.Commands/Extensions/MessageExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Discord.Net.Commands/Extensions/MessageExtensions.cs b/src/Discord.Net.Commands/Extensions/MessageExtensions.cs index a27c5f322..113c1a692 100644 --- a/src/Discord.Net.Commands/Extensions/MessageExtensions.cs +++ b/src/Discord.Net.Commands/Extensions/MessageExtensions.cs @@ -17,7 +17,7 @@ namespace Discord.Commands public static bool HasStringPrefix(this IUserMessage msg, string str, ref int argPos, StringComparison comparisonType = StringComparison.Ordinal) { var text = msg.Content; - if (text.StartsWith(str, comparisonType)) + if (!string.IsNullOrEmpty(text) && text.StartsWith(str, comparisonType)) { argPos = str.Length; return true; From 7f1d37c952f798708da3a635d3f3631f162b0317 Mon Sep 17 00:00:00 2001 From: ComputerMaster1st Date: Tue, 4 Sep 2018 13:52:19 +0100 Subject: [PATCH 7/8] NullRef fix --- src/Discord.Net.Commands/Extensions/MessageExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Discord.Net.Commands/Extensions/MessageExtensions.cs b/src/Discord.Net.Commands/Extensions/MessageExtensions.cs index 113c1a692..f907ed559 100644 --- a/src/Discord.Net.Commands/Extensions/MessageExtensions.cs +++ b/src/Discord.Net.Commands/Extensions/MessageExtensions.cs @@ -27,7 +27,7 @@ namespace Discord.Commands public static bool HasMentionPrefix(this IUserMessage msg, IUser user, ref int argPos) { var text = msg.Content; - if (text.Length <= 3 || text[0] != '<' || text[1] != '@') return false; + if (string.IsNullOrEmpty(text) || text.Length <= 3 || text[0] != '<' || text[1] != '@') return false; int endPos = text.IndexOf('>'); if (endPos == -1) return false; From 2a06bfef1c588e7b7fdcbf99afecaa118684a604 Mon Sep 17 00:00:00 2001 From: ComputerMaster1st Date: Wed, 10 Oct 2018 23:18:24 +0100 Subject: [PATCH 8/8] Removed old code from pull merge --- src/Discord.Net.WebSocket/DiscordSocketClient.cs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/Discord.Net.WebSocket/DiscordSocketClient.cs b/src/Discord.Net.WebSocket/DiscordSocketClient.cs index 355c2fff0..8ea50b07c 100644 --- a/src/Discord.Net.WebSocket/DiscordSocketClient.cs +++ b/src/Discord.Net.WebSocket/DiscordSocketClient.cs @@ -63,7 +63,7 @@ namespace Discord.WebSocket internal WebSocketProvider WebSocketProvider { get; private set; } internal bool AlwaysDownloadUsers { get; private set; } internal int? HandlerTimeout { get; private set; } - + internal new DiscordSocketApiClient ApiClient => base.ApiClient as DiscordSocketApiClient; /// public override IReadOnlyCollection Guilds => State.Guilds; @@ -197,10 +197,10 @@ namespace Discord.WebSocket } /// - public override async Task StartAsync() + public override async Task StartAsync() => await _connection.StartAsync().ConfigureAwait(false); /// - public override async Task StopAsync() + public override async Task StopAsync() => await _connection.StopAsync().ConfigureAwait(false); private async Task OnConnectingAsync() @@ -251,12 +251,8 @@ namespace Discord.WebSocket await heartbeatTask.ConfigureAwait(false); _heartbeatTask = null; -<<<<<<< HEAD // Check if hearbeatTimes is not empty before dequeuing. TryDequeue can cause blocking. if (!_heartbeatTimes.IsEmpty) while (_heartbeatTimes.TryDequeue(out long time)) { } -======= - while (_heartbeatTimes.TryDequeue(out _)) { } ->>>>>>> 8df2c1a1fbc0478f3af6398b705513ad6e8ca20a _lastMessageTime = 0; await _gatewayLogger.DebugAsync("Waiting for guild downloader").ConfigureAwait(false);