Merge pull request #677 from daemitus/fixes

Fixes
This commit is contained in:
goaaats 2021-11-04 14:33:38 +01:00 committed by GitHub
commit ad802d2cbf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 69 additions and 19 deletions

View file

@ -23,9 +23,14 @@ namespace Dalamud.Configuration.Internal
public static bool DalamudNoPlugins { get; } = GetEnvironmentVariable("DALAMUD_NOT_HAVE_PLUGINS"); public static bool DalamudNoPlugins { get; } = GetEnvironmentVariable("DALAMUD_NOT_HAVE_PLUGINS");
/// <summary> /// <summary>
/// Gets a value indicating whether the DalamudForceCoreHook setting has been enabled. /// Gets a value indicating whether the DalamudForceReloaded setting has been enabled.
/// </summary> /// </summary>
public static bool DalamudForceMinHook { get; } = GetEnvironmentVariable("DALAMUD_FORCE_COREHOOK"); public static bool DalamudForceReloaded { get; } = GetEnvironmentVariable("DALAMUD_FORCE_RELOADED");
/// <summary>
/// Gets a value indicating whether the DalamudForceMinHook setting has been enabled.
/// </summary>
public static bool DalamudForceMinHook { get; } = GetEnvironmentVariable("DALAMUD_FORCE_MINHOOK");
private static bool GetEnvironmentVariable(string name) private static bool GetEnvironmentVariable(string name)
=> bool.Parse(Environment.GetEnvironmentVariable(name) ?? "false"); => bool.Parse(Environment.GetEnvironmentVariable(name) ?? "false");

View file

@ -1,12 +1,11 @@
using System; using System;
using System.Diagnostics; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using Dalamud.Configuration.Internal; using Dalamud.Configuration.Internal;
using Dalamud.Hooking.Internal; using Dalamud.Hooking.Internal;
using Dalamud.Memory; using Dalamud.Memory;
using Reloaded.Hooks; using Reloaded.Hooks;
using Serilog;
namespace Dalamud.Hooking namespace Dalamud.Hooking
{ {
@ -29,7 +28,7 @@ namespace Dalamud.Hooking
/// <param name="address">A memory address to install a hook.</param> /// <param name="address">A memory address to install a hook.</param>
/// <param name="detour">Callback function. Delegate must have a same original function prototype.</param> /// <param name="detour">Callback function. Delegate must have a same original function prototype.</param>
public Hook(IntPtr address, T detour) public Hook(IntPtr address, T detour)
: this(address, detour, false) : this(address, detour, false, Assembly.GetCallingAssembly())
{ {
} }
@ -42,9 +41,14 @@ namespace Dalamud.Hooking
/// <param name="detour">Callback function. Delegate must have a same original function prototype.</param> /// <param name="detour">Callback function. Delegate must have a same original function prototype.</param>
/// <param name="useMinHook">Use the MinHook hooking library instead of Reloaded.</param> /// <param name="useMinHook">Use the MinHook hooking library instead of Reloaded.</param>
public Hook(IntPtr address, T detour, bool useMinHook) public Hook(IntPtr address, T detour, bool useMinHook)
: this(address, detour, useMinHook, Assembly.GetCallingAssembly())
{
}
private Hook(IntPtr address, T detour, bool useMinHook, Assembly callingAssembly)
{ {
address = HookManager.FollowJmp(address); address = HookManager.FollowJmp(address);
this.isMinHook = EnvironmentConfiguration.DalamudForceMinHook || useMinHook; this.isMinHook = !EnvironmentConfiguration.DalamudForceReloaded && (EnvironmentConfiguration.DalamudForceMinHook || useMinHook);
var hasOtherHooks = HookManager.Originals.ContainsKey(address); var hasOtherHooks = HookManager.Originals.ContainsKey(address);
if (!hasOtherHooks) if (!hasOtherHooks)
@ -56,9 +60,9 @@ namespace Dalamud.Hooking
this.address = address; this.address = address;
if (this.isMinHook) if (this.isMinHook)
{ {
var indexList = hasOtherHooks if (!HookManager.MultiHookTracker.TryGetValue(address, out var indexList))
? HookManager.MultiHookTracker[address] indexList = HookManager.MultiHookTracker[address] = new();
: HookManager.MultiHookTracker[address] = new();
var index = (ulong)indexList.Count; var index = (ulong)indexList.Count;
this.minHookImpl = new MinSharp.Hook<T>(address, detour, index); this.minHookImpl = new MinSharp.Hook<T>(address, detour, index);
@ -71,7 +75,7 @@ namespace Dalamud.Hooking
this.hookImpl = ReloadedHooks.Instance.CreateHook<T>(detour, address.ToInt64()); this.hookImpl = ReloadedHooks.Instance.CreateHook<T>(detour, address.ToInt64());
} }
HookManager.TrackedHooks.Add(new HookInfo(this, detour, Assembly.GetCallingAssembly())); HookManager.TrackedHooks.Add(new HookInfo(this, detour, callingAssembly));
} }
/// <summary> /// <summary>
@ -188,7 +192,9 @@ namespace Dalamud.Hooking
if (this.isMinHook) if (this.isMinHook)
{ {
this.minHookImpl.Dispose(); this.minHookImpl.Dispose();
HookManager.MultiHookTracker[this.address] = null;
var index = HookManager.MultiHookTracker[this.address].IndexOf(this);
HookManager.MultiHookTracker[this.address][index] = null;
} }
else else
{ {

View file

@ -196,7 +196,7 @@ namespace Dalamud.Interface.Internal.Windows
if (ImGui.IsItemHovered()) if (ImGui.IsItemHovered())
ImGui.SetTooltip("Kill game"); ImGui.SetTooltip("Kill game");
ImGui.BeginChild("scrolling", new Vector2(0, ImGui.GetFrameHeightWithSpacing() - 55), false, ImGuiWindowFlags.HorizontalScrollbar); ImGui.BeginChild("scrolling", new Vector2(0, ImGui.GetFrameHeightWithSpacing() - 55), false, ImGuiWindowFlags.AlwaysHorizontalScrollbar | ImGuiWindowFlags.AlwaysVerticalScrollbar);
if (clear) if (clear)
{ {

View file

@ -1564,6 +1564,8 @@ namespace Dalamud.Interface.Internal.Windows
if (ImGui.CollapsingHeader($"#{task.Id} - {task.Status} {(subTime - task.StartTime).TotalMilliseconds}ms###task{i}")) if (ImGui.CollapsingHeader($"#{task.Id} - {task.Status} {(subTime - task.StartTime).TotalMilliseconds}ms###task{i}"))
{ {
task.IsBeingViewed = true;
if (ImGui.Button("CANCEL (May not work)")) if (ImGui.Button("CANCEL (May not work)"))
{ {
try try
@ -1589,6 +1591,10 @@ namespace Dalamud.Interface.Internal.Windows
ImGui.TextUnformatted(task.Exception.ToString()); ImGui.TextUnformatted(task.Exception.ToString());
} }
} }
else
{
task.IsBeingViewed = false;
}
ImGui.PopStyleColor(1); ImGui.PopStyleColor(1);
} }

View file

@ -15,6 +15,7 @@ namespace Dalamud.Logging.Internal
/// </summary> /// </summary>
internal class TaskTracker : IDisposable internal class TaskTracker : IDisposable
{ {
private static readonly ModuleLog Log = new("TT");
private static readonly List<TaskInfo> TrackedTasksInternal = new(); private static readonly List<TaskInfo> TrackedTasksInternal = new();
private static readonly ConcurrentQueue<TaskInfo> NewlyCreatedTasks = new(); private static readonly ConcurrentQueue<TaskInfo> NewlyCreatedTasks = new();
private static bool clearRequested = false; private static bool clearRequested = false;
@ -53,12 +54,33 @@ namespace Dalamud.Logging.Internal
clearRequested = false; clearRequested = false;
} }
var i = 0;
var pruned = 0;
// Prune old tasks. Technically a memory "leak" that grows infinitely otherwise.
while (i < TrackedTasksInternal.Count)
{
var taskInfo = TrackedTasksInternal[i];
if (taskInfo.IsCompleted && !taskInfo.IsBeingViewed && TrackedTasksInternal.Count > 1000)
{
TrackedTasksInternal.RemoveAt(i);
pruned++;
continue;
}
i++;
}
// if (pruned > 0)
// Log.Debug($"Pruned {pruned} tasks");
// Consume from a queue to prevent iteration errors
while (NewlyCreatedTasks.TryDequeue(out var newTask)) while (NewlyCreatedTasks.TryDequeue(out var newTask))
{ {
TrackedTasksInternal.Add(newTask); TrackedTasksInternal.Add(newTask);
} }
for (var i = 0; i < TrackedTasksInternal.Count; i++) // Update each task
for (i = 0; i < TrackedTasksInternal.Count; i++)
{ {
var taskInfo = TrackedTasksInternal[i]; var taskInfo = TrackedTasksInternal[i];
if (taskInfo.Task == null) if (taskInfo.Task == null)
@ -123,10 +145,16 @@ namespace Dalamud.Logging.Internal
var patchMethod = typeof(TaskTracker).GetMethod(nameof(AddToActiveTasksHook), BindingFlags.NonPublic | BindingFlags.Static); var patchMethod = typeof(TaskTracker).GetMethod(nameof(AddToActiveTasksHook), BindingFlags.NonPublic | BindingFlags.Static);
if (targetMethod == null) if (targetMethod == null)
Log.Error("TargetMethod null!"); {
Log.Error("AddToActiveTasks TargetMethod null!");
return;
}
if (patchMethod == null) if (patchMethod == null)
Log.Error("PatchMethod null!"); {
Log.Error("AddToActiveTasks PatchMethod null!");
return;
}
this.scheduleAndStartHook = new MonoMod.RuntimeDetour.Hook(targetMethod, patchMethod); this.scheduleAndStartHook = new MonoMod.RuntimeDetour.Hook(targetMethod, patchMethod);
@ -173,6 +201,11 @@ namespace Dalamud.Logging.Internal
/// </summary> /// </summary>
public bool IsCompletedSuccessfully { get; set; } public bool IsCompletedSuccessfully { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this task is being viewed.
/// </summary>
public bool IsBeingViewed { get; set; }
/// <summary> /// <summary>
/// Gets or sets the status of the task. /// Gets or sets the status of the task.
/// </summary> /// </summary>

View file

@ -478,8 +478,8 @@ namespace Dalamud
WM_INPUT_DEVICE_CHANGE = 0x00FE, WM_INPUT_DEVICE_CHANGE = 0x00FE,
WM_INPUT = 0x00FF, WM_INPUT = 0x00FF,
WM_KEYFIRST = WM_KEYDOWN, WM_KEYFIRST = 0x0100,
WM_KEYDOWN = 0x0100, WM_KEYDOWN = WM_KEYFIRST,
WM_KEYUP = 0x0101, WM_KEYUP = 0x0101,
WM_CHAR = 0x0102, WM_CHAR = 0x0102,
WM_DEADCHAR = 0x0103, WM_DEADCHAR = 0x0103,
@ -525,8 +525,8 @@ namespace Dalamud
WM_CTLCOLORSTATIC = 0x0138, WM_CTLCOLORSTATIC = 0x0138,
MN_GETHMENU = 0x01E1, MN_GETHMENU = 0x01E1,
WM_MOUSEFIRST = WM_MOUSEMOVE, WM_MOUSEFIRST = 0x0200,
WM_MOUSEMOVE = 0x0200, WM_MOUSEMOVE = WM_MOUSEFIRST,
WM_LBUTTONDOWN = 0x0201, WM_LBUTTONDOWN = 0x0201,
WM_LBUTTONUP = 0x0202, WM_LBUTTONUP = 0x0202,
WM_LBUTTONDBLCLK = 0x0203, WM_LBUTTONDBLCLK = 0x0203,