From dcedf91d9e8ed6064705cc4dcad372923388e498 Mon Sep 17 00:00:00 2001 From: Kamron Batman <3953314+kamronbatman@users.noreply.github.com> Date: Sun, 19 Jul 2026 22:31:50 -0700 Subject: [PATCH] =?UTF-8?q?fix(advanced-search):=20upstream=20polish=20?= =?UTF-8?q?=E2=80=94=20guard=20DoSearch=20drain,=20Yield=20in=20worker=20d?= =?UTF-8?q?rain,=20drop=20dead=20ParseValue=20surface?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Engines/Advanced Search/AdvancedSearchGump.cs | 10 ++++++++++ .../Advanced Search/AdvancedSearchThreadWorker.cs | 6 ++++-- .../Engines/Advanced Search/AdvancedSearchUtilities.cs | 6 ------ 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/Projects/UOContent/Engines/Advanced Search/AdvancedSearchGump.cs b/Projects/UOContent/Engines/Advanced Search/AdvancedSearchGump.cs index cc3a0a20d..869e98cf7 100644 --- a/Projects/UOContent/Engines/Advanced Search/AdvancedSearchGump.cs +++ b/Projects/UOContent/Engines/Advanced Search/AdvancedSearchGump.cs @@ -8,6 +8,7 @@ using Server.Commands; using Server.Commands.Generic; using Server.Engines.Spawners; using Server.Gumps; +using Server.Logging; using Server.Network; using Server.Saves; @@ -28,6 +29,8 @@ public enum AdvancedSearchGumpOptions : long public class AdvancedSearchGump : Gump { + private static readonly ILogger _logger = LogFactory.GetLogger(typeof(AdvancedSearchGump)); + private const int MaxEntries = 18; private static int _threadId; @@ -828,6 +831,13 @@ public class AdvancedSearchGump : Gump // Send the gump on the main thread Core.LoopContext.Post(() => Resend(from)); } + catch (Exception ex) + { + // Never let a drain-phase failure escape unhandled on the ThreadPool + // thread - that would terminate the process. The finally below still + // restores autosave and releases the search guard. + _logger.Warning(ex, "AdvancedSearch: search drain failed"); + } finally { AutoSave.SavesEnabled = (bool)state!; diff --git a/Projects/UOContent/Engines/Advanced Search/AdvancedSearchThreadWorker.cs b/Projects/UOContent/Engines/Advanced Search/AdvancedSearchThreadWorker.cs index 74dd6a41d..62be513a8 100644 --- a/Projects/UOContent/Engines/Advanced Search/AdvancedSearchThreadWorker.cs +++ b/Projects/UOContent/Engines/Advanced Search/AdvancedSearchThreadWorker.cs @@ -118,8 +118,10 @@ public class AdvancedSearchThreadWorker } else { - // Queue is transiently empty but we're not paused yet; avoid a 100%-CPU busy-spin. - Thread.SpinWait(1); + // Queue is transiently empty but we're not paused yet; yield the core to + // other runnable threads (e.g. the other still-filtering workers) instead + // of busy-spinning. + Thread.Yield(); } } diff --git a/Projects/UOContent/Engines/Advanced Search/AdvancedSearchUtilities.cs b/Projects/UOContent/Engines/Advanced Search/AdvancedSearchUtilities.cs index 44a694ef1..adc793241 100644 --- a/Projects/UOContent/Engines/Advanced Search/AdvancedSearchUtilities.cs +++ b/Projects/UOContent/Engines/Advanced Search/AdvancedSearchUtilities.cs @@ -273,12 +273,6 @@ public static class AdvancedSearchUtilities return false; } - public static T ParseValue(ReadOnlySpan valuePart) - { - TryParseValue(valuePart, out T value); - return value; - } - internal static bool TryParseValue(ReadOnlySpan valuePart, out T value) { // Special handling for boolean and hexadecimal values