Swallow all exceptions in async void methods

Otherwise an uncaught exception will terminate the whole process :(
This commit is contained in:
13xforever
2018-10-01 22:10:43 +05:00
committed by Roberto Anić Banić
parent eef13b3d01
commit 605a5c67be
4 changed files with 101 additions and 78 deletions

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
@@ -6,6 +7,7 @@ using System.Threading.Tasks;
using CompatBot.Commands.Attributes;
using CompatBot.EventHandlers;
using CompatBot.Utils;
using DSharpPlus;
using DSharpPlus.CommandsNext;
using DSharpPlus.CommandsNext.Attributes;
using DSharpPlus.Entities;
@@ -35,6 +37,7 @@ namespace CompatBot.Commands
await ctx.RespondAsync("Another check is already in progress").ConfigureAwait(false);
return;
}
try
{
await ctx.TriggerTypingAsync().ConfigureAwait(false);
@@ -63,6 +66,12 @@ namespace CompatBot.Commands
else
await ctx.RespondAsync("No potential name spoofing was detected").ConfigureAwait(false);
}
catch (Exception e)
{
ctx.Client.DebugLogger.LogMessage(LogLevel.Error, "", e.ToString(), DateTime.Now);
//should be extra careful, as async void will run on a thread pull, and will terminate the whole application with an uncaught exception
try { await ctx.ReactWithAsync(Config.Reactions.Failure, "(X_X)").ConfigureAwait(false); } catch { }
}
finally
{
CheckLock.Release(1);

View File

@@ -50,98 +50,106 @@ namespace CompatBot.EventHandlers
public static async void BackgroundProcessor(MessageCreateEventArgs args)
{
var message = args.Message;
if (!QueueLimiter.Wait(0))
{
await args.Channel.SendMessageAsync("Log processing is rate limited, try again a bit later").ConfigureAwait(false);
return;
}
bool parsedLog = false;
var startTime = Stopwatch.StartNew();
try
{
foreach (var attachment in message.Attachments.Where(a => a.FileSize < Config.AttachmentSizeLimit))
foreach (var handler in handlers)
if (await handler.CanHandleAsync(attachment).ConfigureAwait(false))
{
await args.Channel.TriggerTypingAsync().ConfigureAwait(false);
Console.WriteLine($">>>>>>> {message.Id%100} Parsing log from attachment {attachment.FileName} ({attachment.FileSize})...");
parsedLog = true;
LogParseState result = null;
try
{
var pipe = new Pipe();
var fillPipeTask = handler.FillPipeAsync(attachment, pipe.Writer);
result = await LogParser.ReadPipeAsync(pipe.Reader).ConfigureAwait(false);
await fillPipeTask.ConfigureAwait(false);
}
catch (Exception e)
{
args.Client.DebugLogger.LogMessage(LogLevel.Error, "", "Log parsing failed: " + e, DateTime.Now);
}
if (result == null)
await args.Channel.SendMessageAsync("Log analysis failed, most likely cause is a truncated/invalid log. Please run the game again and reupload the new copy.").ConfigureAwait(false);
else
var message = args.Message;
if (!QueueLimiter.Wait(0))
{
await args.Channel.SendMessageAsync("Log processing is rate limited, try again a bit later").ConfigureAwait(false);
return;
}
bool parsedLog = false;
var startTime = Stopwatch.StartNew();
try
{
foreach (var attachment in message.Attachments.Where(a => a.FileSize < Config.AttachmentSizeLimit))
foreach (var handler in handlers)
if (await handler.CanHandleAsync(attachment).ConfigureAwait(false))
{
await args.Channel.TriggerTypingAsync().ConfigureAwait(false);
Console.WriteLine($">>>>>>> {message.Id % 100} Parsing log from attachment {attachment.FileName} ({attachment.FileSize})...");
parsedLog = true;
LogParseState result = null;
try
{
if (result.Error == LogParseState.ErrorCode.PiracyDetected)
{
if (args.Author.IsWhitelisted(args.Client, args.Guild))
{
await Task.WhenAll(
args.Channel.SendMessageAsync("I see wha' ye did thar ☠"),
args.Client.ReportAsync("Pirated Release (whitelisted by role)", args.Message, result.PiracyTrigger, result.PiracyContext, ReportSeverity.Low)
).ConfigureAwait(false);
}
else
{
var severity = ReportSeverity.Low;
try
{
await message.DeleteAsync("Piracy detected in log").ConfigureAwait(false);
}
catch (Exception e)
{
severity = ReportSeverity.High;
args.Client.DebugLogger.LogMessage(LogLevel.Warning, "", $"Unable to delete message in {args.Channel.Name}: {e.Message}", DateTime.Now);
}
await args.Channel.SendMessageAsync(embed: await result.AsEmbedAsync(args.Client, args.Message).ConfigureAwait(false)).ConfigureAwait(false);
await Task.WhenAll(
args.Client.ReportAsync("Pirated Release", args.Message, result.PiracyTrigger, result.PiracyContext, severity),
Warnings.AddAsync(args.Client, args.Message, args.Message.Author.Id, args.Message.Author.Username, args.Client.CurrentUser,
"Pirated Release", $"{message.Content.Sanitize()} - {result.PiracyTrigger}")
);
}
}
else
await args.Channel.SendMessageAsync(embed: await result.AsEmbedAsync(args.Client, args.Message).ConfigureAwait(false)).ConfigureAwait(false);
var pipe = new Pipe();
var fillPipeTask = handler.FillPipeAsync(attachment, pipe.Writer);
result = await LogParser.ReadPipeAsync(pipe.Reader).ConfigureAwait(false);
await fillPipeTask.ConfigureAwait(false);
}
catch (Exception e)
{
args.Client.DebugLogger.LogMessage(LogLevel.Error, "", "Sending log results failed: " + e, DateTime.Now);
args.Client.DebugLogger.LogMessage(LogLevel.Error, "", "Log parsing failed: " + e, DateTime.Now);
}
if (result == null)
await args.Channel.SendMessageAsync("Log analysis failed, most likely cause is a truncated/invalid log. Please run the game again and reupload the new copy.")
.ConfigureAwait(false);
else
{
try
{
if (result.Error == LogParseState.ErrorCode.PiracyDetected)
{
if (args.Author.IsWhitelisted(args.Client, args.Guild))
{
await Task.WhenAll(
args.Channel.SendMessageAsync("I see wha' ye did thar ☠"),
args.Client.ReportAsync("Pirated Release (whitelisted by role)", args.Message, result.PiracyTrigger, result.PiracyContext, ReportSeverity.Low)
).ConfigureAwait(false);
}
else
{
var severity = ReportSeverity.Low;
try
{
await message.DeleteAsync("Piracy detected in log").ConfigureAwait(false);
}
catch (Exception e)
{
severity = ReportSeverity.High;
args.Client.DebugLogger.LogMessage(LogLevel.Warning, "", $"Unable to delete message in {args.Channel.Name}: {e.Message}", DateTime.Now);
}
await args.Channel.SendMessageAsync(embed: await result.AsEmbedAsync(args.Client, args.Message).ConfigureAwait(false)).ConfigureAwait(false);
await Task.WhenAll(
args.Client.ReportAsync("Pirated Release", args.Message, result.PiracyTrigger, result.PiracyContext, severity),
Warnings.AddAsync(args.Client, args.Message, args.Message.Author.Id, args.Message.Author.Username, args.Client.CurrentUser,
"Pirated Release", $"{message.Content.Sanitize()} - {result.PiracyTrigger}")
);
}
}
else
await args.Channel.SendMessageAsync(embed: await result.AsEmbedAsync(args.Client, args.Message).ConfigureAwait(false)).ConfigureAwait(false);
}
catch (Exception e)
{
args.Client.DebugLogger.LogMessage(LogLevel.Error, "", "Sending log results failed: " + e, DateTime.Now);
}
}
return;
}
if (string.IsNullOrEmpty(message.Content) || !"help".Equals(args.Channel.Name, StringComparison.InvariantCultureIgnoreCase))
return;
var linkStart = message.Content.IndexOf("http");
if (linkStart > -1)
{
var link = message.Content.Substring(linkStart).Split(linkSeparator, 2)[0];
if (link.Contains(".log", StringComparison.InvariantCultureIgnoreCase) || link.Contains("rpcs3.zip", StringComparison.CurrentCultureIgnoreCase))
await args.Channel.SendMessageAsync("If you intended to upload a log file please re-upload it directly to discord").ConfigureAwait(false);
}
if (string.IsNullOrEmpty(message.Content) || !"help".Equals(args.Channel.Name, StringComparison.InvariantCultureIgnoreCase))
return;
var linkStart = message.Content.IndexOf("http");
if (linkStart > -1)
}
finally
{
var link = message.Content.Substring(linkStart).Split(linkSeparator, 2)[0];
if (link.Contains(".log", StringComparison.InvariantCultureIgnoreCase) || link.Contains("rpcs3.zip", StringComparison.CurrentCultureIgnoreCase))
await args.Channel.SendMessageAsync("If you intended to upload a log file please reupload it directly to discord").ConfigureAwait(false);
QueueLimiter.Release();
if (parsedLog)
Console.WriteLine($"<<<<<<< {message.Id % 100} Finished parsing in {startTime.Elapsed}");
}
}
finally
catch (Exception e)
{
QueueLimiter.Release();
if (parsedLog)
Console.WriteLine($"<<<<<<< {message.Id % 100} Finished parsing in {startTime.Elapsed}");
args.Client.DebugLogger.LogMessage(LogLevel.Error, "", e.ToString(), DateTime.Now);
}
}
}

View File

@@ -8,6 +8,7 @@ using System.Threading.Tasks;
using CompatBot.Database;
using CompatBot.Database.Providers;
using CompatBot.EventHandlers;
using DSharpPlus;
using DSharpPlus.CommandsNext;
using PsnClient.POCOs;
using PsnClient.Utils;
@@ -82,6 +83,10 @@ namespace CompatBot.ThumbScrapper
}
await ctx.RespondAsync($"Didn't find {contentId} in any PSN store").ConfigureAwait(false);
}
catch (Exception e)
{
ctx.Client.DebugLogger.LogMessage(LogLevel.Error, "", e.ToString(), DateTime.Now);
}
finally
{
QueueLimiter.Release();

View File

@@ -45,7 +45,8 @@ namespace CompatBot.Utils
{
if (buffer.Length + line.Length + blockEnd.Length > blockSize)
{
await channel.SendMessageAsync(buffer.Append(blockEnd).ToString()).ConfigureAwait(false);
var content = buffer.ToString().Trim(blockSize - blockEnd.Length) + blockEnd;
await channel.SendMessageAsync(content).ConfigureAwait(false);
await channel.TriggerTypingAsync().ConfigureAwait(false);
buffer.Clear().Append(blockStart);
}