Skip to content

Two crashes, one name

Topicscrash, physx, diagnosis, instrumentation

This week I posted about the mod on Reddit. Seven thousand views, forty-five upvotes: fine. What I actually got out of it was one comment telling me where Cyberpunk keeps its crash reports. A hidden folder, one directory per crash, and in each one a memory dump and three plain text files. I had spent days guessing at crashes while a report sat waiting for me after every single one.

There were fifty-six of them, going back to 17 August. An afternoon and a small script got me through them, and the first thing they said was that I had been chasing one problem that was really two. The two do not overlap by a single second. One kills the game fifteen to forty-seven seconds after launch, with about six hundred megabytes of video memory in use. That is the main menu, not a loaded city, and none of the mod’s systems has started running yet. The other kills it anywhere from two to twenty-three minutes in, with four gigabytes or more. Every crash in the pile is cleanly one or the other.

The early one is thirty-eight of the fifty-six, and it is not ours. It is the same graphics driver fault every time, at the same address, and the proof that finally satisfied me came from outside the game entirely. Windows keeps its own log of driver faults, and fifty-six of the fifty-seven entries in it land in the ninety seconds before one of these crashes. No script I can write reaches down to that log. It does not follow the work either: the day with sixty commits and twenty-four launches had none of these crashes, and a day with no commits at all had seven.

That leaves four crashes that are ours, all in the physics engine, and this is where it stopped being merely tidy and got interesting. Four crashes, four different places in the physics code, four different garbage addresses. If we were getting an index wrong, it would fail in the same place every time. Four different places means the list the physics engine is walking through has something dead in it: we are pulling a car out from under physics while physics is still reading it.

The number that closed it was one I had been printing all week and never once looked at. Every trace line we write carries the ID of the thread that wrote it, the lane of work it ran on, and each crash folder is named after the thread that died. Same thread. The parts of our code we schedule to run a moment later are running on the engine’s own worker threads, the same ones doing the physics. That had been an argument all day. It stopped being one the moment those two numbers matched.

The candidate fix is small, and it comes down to a question I had been asking wrong in six places. Before touching the getaway car we checked that it was still there, except the check only asked whether the script’s handle on the car was still alive. That says nothing about whether the car is still attached to the world, and everything we do next touches its physical body: speed, skid, its slot in traffic. The game’s own code asks that second question before it touches anything. Now so do we, in all six.

It is deployed and nobody has played a single game on it. If the crash comes back with this in place, the theory is dead, and I stop guessing which system cancels the escape order and go ask the engine directly. Which, it turns out, it will tell me, if I hook into the right place.