From 25a4ab62ad61948a0ec776f4cc2b9b469b02dbba Mon Sep 17 00:00:00 2001 From: rabbitstack Date: Thu, 5 Mar 2026 18:51:05 +0100 Subject: [PATCH] perf(symbolizer): Cache unsuccessful debug help resolutions If the process handle can't be acquired or the symbol handler initialization fails, we cache the symbol info to avoid hammering the OpenProcess API indefinitely. --- pkg/symbolize/symbolizer.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pkg/symbolize/symbolizer.go b/pkg/symbolize/symbolizer.go index d8c779fc8..ee5e8d98e 100644 --- a/pkg/symbolize/symbolizer.go +++ b/pkg/symbolize/symbolizer.go @@ -535,12 +535,16 @@ func (s *Symbolizer) produceFrame(addr va.Address, e *event.Event) callstack.Fra if !ok { handle, err := windows.OpenProcess(windows.SYNCHRONIZE|windows.PROCESS_QUERY_INFORMATION, false, pid) if err != nil { + // symbol handler initalization fails, cache + // the symbol for future lookups + s.cacheSymbolUnbacked(pid, addr, &frame) return frame } // initialize symbol handler opts := uint32(sys.SymUndname | sys.SymCaseInsensitive | sys.SymAutoPublics | sys.SymOmapFindNearest | sys.SymDeferredLoads) err = s.r.Initialize(handle, opts) if err != nil { + s.cacheSymbolUnbacked(pid, addr, &frame) return frame } proc = &process{pid, handle, time.Now(), 1} @@ -654,6 +658,13 @@ func (s *Symbolizer) cacheSymbol(pid uint32, addr va.Address, frame *callstack.F } } +func (s *Symbolizer) cacheSymbolUnbacked(pid uint32, addr va.Address, frame *callstack.Frame) { + if frame.Module == "?" { + frame.Module = "unbacked" + } + s.cacheSymbol(pid, addr, frame) +} + func (s *Symbolizer) cleanSym() { s.mu.Lock() defer s.mu.Unlock()