You are viewing a potentially older version of this package. View all versions.
CatLib-CrashWatcher-1.1.0 icon

CrashWatcher

The crash window of CatLib: a small Windows program that waits for the game to close and, if it crashed or froze, shows what happened and keeps a report. Comes with CatLib.

Date uploaded 3 days ago
Version 1.1.0
Download link CatLib-CrashWatcher-1.1.0.zip
Downloads 66
Dependency string CatLib-CrashWatcher-1.1.0

README

CatLib Crash Watcher

The crash window of CatLib. You don't need to install it yourself: it comes with CatLib.

When Cat Mail Co. closes by itself or freezes while quitting, a small window tells you what happened in your language and keeps a report folder with everything a mod author needs to fix it. Send that folder with your bug report.

What it does

  • Starts together with the game and waits for it to close. On a normal quit it closes too and leaves nothing behind.
  • After a crash it shows a small window: what happened in one line, the details, and buttons to open the report folder or copy the report.
  • Keeps the report in BepInEx/CatLib/Crashes: the report, both game logs and a memory dump of the moment of the crash. Only the last 10 reports are kept, dumps only in the last 3.
  • Notices when the game hangs while quitting and says so in the report.
  • Names the method of the game the crash happened in and writes down what every thread of the game was doing at that moment, so a mod author sees where it broke without opening the memory dump.

What it doesn't do

  • It sends nothing anywhere. The report stays on your computer until you attach it yourself.
  • The only thing it downloads: the public symbols of Unity and Windows, once per version, from the symbol servers of Unity and Microsoft. They let reports name the functions inside UnityPlayer.dll and Windows. They are kept in BepInEx/CatLib/Symbols.
  • It doesn't change the game. To write a memory dump it follows the game the way a debugger does, which pauses the game only for the moment of writing and of reading the threads.

It is a separate Windows program, CatLib.CrashWatcher.exe, because a program can't report its own crash reliably from the inside. Source code: tools/CatLib.CrashWatcher, how it works: Crash reports.

Settings

Settings → Mods → CatLib:

  • Crash window: turn the whole thing off.
  • Crash dump: keep the window and the report, but without the memory dump.
  • Crash symbols: don't download the symbols of Unity and Windows.

Found a bug?

Report it on GitHub. If the crash window itself misbehaved, attach BepInEx/CatLib/Crashes/watcher.log too.

CHANGELOG

Changelog

1.1.0

  • Reports name the method of the game a crash happened in, for example EntityInteractableStore.Start() + 0x60 instead of only GameAssembly.dll + 0x4d5f30. The names come from BepInEx/interop/MethodAddressToToken.db, which BepInEx writes with the interop assemblies; the watcher reads it only after a crash and checks that it belongs to the running game build.
  • Every report of a crash or a hang has the stacks of all game threads: the crashing thread and the game thread in report.txt, every thread in stacks.txt, threads with the same stack grouped. The watcher walks them with the unwind data of the game's DLLs while the game is stopped at the crash, or pauses it for a moment when it hangs.
  • Frames outside the game's methods say what they are: the IL2CPP runtime, generic code of IL2CPP, a function a DLL exports, or .NET code compiled while the game runs. Frames found by searching the stack are marked with ?.
  • When the crash is in Windows, Unity or another DLL, the report and the window also name the nearest method of the game on the crashing thread, for example the method that called RaiseException.
  • A call through a bad pointer shows the bad address as "not code" and the frame that made the call below it.
  • C++ names of exported functions are shown readable, for example il2cpp_baselib::Baselib_SystemFutex_Wait.
  • The window shows the method next to the module in the details.
  • Generic methods have names: the watcher reads the IL2CPP metadata (global-metadata.dat) and the registrations in GameAssembly.dll itself, so a frame shows Dictionary<string, int>.TryInsert(string, int, InsertionBehavior) instead of "IL2CPP code that is not a game method". It reads metadata versions 29 to 106 and uses them only when they agree with the BepInEx method map.
  • Functions of UnityPlayer.dll, baselib.dll, the game's .exe, ntdll.dll, KERNELBASE.dll, kernel32.dll and coreclr.dll have names from their public symbols. The watcher downloads them from the symbol servers of Unity and Microsoft once per version, half a minute after the game starts, into BepInEx/CatLib/Symbols; --no-symbols turns the downloads off. A .pdb next to a DLL is used first.
  • C++ names are shown the way Windows undecorates them, for example ScriptingInvocation::Invoke.
  • Symbols are also downloaded for user32.dll, win32u.dll, d3d11.dll, dxgi.dll, the C runtime and clrjit.dll.
  • When a crash is inside Windows or the C runtime, such as RaiseException, the report, the window and watcher.log name the first frame outside them in a "Called from" line.
  • Methods interop gave a made-up name, like Method_Private_IEnumerator_PDM_0, show their original name from the IL2CPP metadata with the interop name after it.
  • Code IL2CPP shares between all type arguments shows the generic parameter names, QuickSort<T>(Span<T>, …), and nested types of generic types read like C#, Dictionary<int, string>.Enumerator.

1.0.2

  • A stack overflow keeps its memory dump. .NET closes the game with 0x800703E9 after a stack overflow, the watcher took that for another exit and removed the dump it wrote when the overflow happened. Now that dump stays, and the report names the place of the overflow instead of "no crash record". The same goes for any crash within 10 seconds after an exception the game did not survive.
  • The exit code 0x800703E9 is named as a stack overflow.
  • The game no longer closes when it stops at a breakpoint. Steam and other libraries stop there only when a debugger follows the game, and the watcher is one, so the game closed with 0x80000003 where it goes on without the watcher, for example when the host returned to the menu right after a player left. The watcher now lets the game go on and writes the first stops into its log.

1.0.0

  • A package of its own. Until now the crash watcher came inside CatLib (0.6.0 and 0.6.1); CatLib 0.6.2 and later depend on this package and find the program in any folder of BepInEx/plugins.
  • The crash window in every language of the game, with a different cozy phrase every time, the details, and buttons to open the report folder and to copy the report.
  • A report folder in BepInEx/CatLib/Crashes for every crash: the report for mod authors, both game logs, the recorded session and a memory dump.
  • Memory dumps of the moment of the crash, also for crashes that Unity closes itself on the game thread.
  • A hang while quitting is noticed after 8 seconds, with a dump of every thread at that moment.
  • The report names its own version and warns when CatLib records more than this version can read.