Skip to content

Recovery Hooks

BlueShank edited this page Sep 1, 2026 · 1 revision

Some freezes are recoverable, for example a stuck Lua loop can be broken (loopbreak).
When that happens, the plugin fires standard Garry's Mod hooks so your addons can react, for example notify staff, log to a database, or clean up the offending entity.

The hooks run on the game thread at the next safe tick, so it's safe to do normal Lua work in them.

Hook Fires when
crashcapture.loopbreak A suspected infinite Lua loop was interrupted.
crashcapture.physresume A physics fault was resumed.
crashcapture.physresolve A physics hang was mitigated.
crashcapture.recovery Any time the game thread recovers from a freeze.

Each hook receives a single info table.
Fields are present only when known:

  • info.method - "loopbreak", "physresume", or nil (self-recovered).
  • info.stall - where the stall was: "physics", "native", "lua", "lua-jit".
  • info.reason - the one-line freeze reason (same text as the report).
  • info.report - path to the full report file.
  • info.downtime - milliseconds the game thread was stalled (recovery only).
  • info.stack? - array of "source:line in name" strings captured from the stuck Lua call stack.
  • info.entities? - physresolve only: array of entity indices the plugin flagged as the offending physics objects (see below).

Examples

hook.Add("crashcapture.recovery", "notify_recovery", function(info)
    print(("[Crash Capture] recovered via %s after %dms (%s)")
        :format(info.method or "self", info.downtime or 0, info.stall or "?"))
    if info.report then print("  report:", info.report) end
end)

hook.Add("crashcapture.loopbreak", "log_loop", function(info)
    for _, frame in ipairs(info.stack or {}) do print("  ", frame) end
end)

hook.Add("crashcapture.physresolve", "remove_offenders", function(info)
    for _, idx in ipairs(info.entities or {}) do
        local ent = Entity(idx)
        if IsValid(ent) then
            print("[Crash Capture] run away entity #" .. idx)
        end
    end
end)

About physresolve

  • It fires a few frames after the hang is caught (tunable via the phys_resolve_delay setting), so physics has settled before your handler runs.
  • Players, NPCs and physgun-held props are never reported, so you won't be handed something you shouldn't delete.
  • If a contraption keeps re-triggering, the same entity can show up across repeated episodes (deduped within one window, not forever), so keep your handler idempotent, the IsValid check above is enough.
  • phys_pin is for if you need crash capture to handle freezing, this tends to be unstable and we recommend handling it in lua itself.

Clone this wiki locally