Five bugs identified and patched in retail Asheron's Call client: - v3b: palette refcount over-increment (3-byte NOP at two sites) - v5: RenderSurface PurgeResource no-op stub (vtable slot 2 thunk) - v11: two dangling-pointer crash guards (NULL-check + reorder) - v14: CEnvCell::Destroy ClipPlaneList leak (18-byte JMP to cleanup thunk) - v22: unpacker stale-pointer SEH guard (whole-function __try/__except) All five ship in leakfix.dll (117 KB, SHA d282f23c…) which is loaded by acclient.exe at process start via PE import table patching by tools/install_leakfix.py. Controlled 15-client fleet soak: unpatched control died at 26h with palette exhaustion; all 14 patched clients survived past that point and reached ≥5-day uptime. Residual ~15 MB/h growth traced to d3d9.dll's internal slab allocator (260KB surface backing buffers retained after Release). See REPORT.md §10 for the full investigation; conclusion is that it's unfixable from outside d3d9. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
71 lines
2.1 KiB
AutoHotkey
71 lines
2.1 KiB
AutoHotkey
; bench_roundtrip.ahk
|
|
; Phase 0 step 4 — drive the AC client through char-select → in-world → clean quit,
|
|
; without a human watching. Logs to artifacts/phase0/ahk_roundtrip.log.
|
|
;
|
|
; Run with: AutoHotkey64.exe bench_roundtrip.ahk
|
|
|
|
#Requires AutoHotkey v2.0
|
|
#SingleInstance Force
|
|
|
|
WinTitle := "Asheron's Call"
|
|
LogFile := "C:\Users\acbot\leakhunt\artifacts\phase0\ahk_roundtrip.log"
|
|
|
|
Log(msg) {
|
|
global LogFile
|
|
FileAppend Format("[{1}] {2}`n", FormatTime(A_Now, "yyyy-MM-dd HH:mm:ss"), msg), LogFile
|
|
}
|
|
|
|
Log("script start")
|
|
|
|
if not WinWait(WinTitle, , 30) {
|
|
Log("FATAL: AC window not found within 30s")
|
|
ExitApp 1
|
|
}
|
|
Log("AC window found")
|
|
|
|
WinActivate WinTitle
|
|
Sleep 1500
|
|
if not WinActive(WinTitle) {
|
|
Log("WARN: WinActivate did not bring AC to foreground; trying ControlSend fallback")
|
|
}
|
|
|
|
; Phase A: if at char-select, Enter selects the default (only) character and enters world.
|
|
; If we're already in-world (memory >800 MB suggested by the supervisor probe), Enter opens
|
|
; chat which we'll close immediately.
|
|
SendInput "{Enter}"
|
|
Log("sent Enter #1 (char-select confirm or chat-open)")
|
|
Sleep 2000
|
|
|
|
; Phase B: send Escape to dismiss any modal/chat that may have opened. Harmless if no modal.
|
|
SendInput "{Esc}"
|
|
Log("sent Escape (dismiss modal/chat)")
|
|
Sleep 800
|
|
|
|
; Phase C: small movement step to satisfy "walk one step" requirement (Phase 0 §4).
|
|
; W is the AC default forward-walk bind in most layouts. Hold 250 ms.
|
|
SendInput "{w down}"
|
|
Sleep 250
|
|
SendInput "{w up}"
|
|
Log("sent W pulse (walk one step)")
|
|
Sleep 1000
|
|
|
|
; Phase D: clean quit. AC supports @quit chat command to log out to character select.
|
|
; Then we send /quit again from char-select to terminate the client process gracefully.
|
|
SendInput "{Enter}" ; open chat
|
|
Sleep 200
|
|
SendInput "@quit"
|
|
Sleep 200
|
|
SendInput "{Enter}"
|
|
Log("sent @quit (logout-to-char-select)")
|
|
Sleep 4000
|
|
|
|
; If still alive at char-select: ask the launcher menu to exit the client.
|
|
; AC's exit-to-desktop on char-select is typically Escape -> Yes-to-exit confirmation.
|
|
SendInput "{Esc}"
|
|
Sleep 600
|
|
SendInput "{Enter}" ; default focus on "Quit" or "Yes"
|
|
Log("sent Escape + Enter (exit from char-select)")
|
|
|
|
Sleep 1500
|
|
Log("script end")
|
|
ExitApp 0
|