Saltar al contenido

Dos crashes bajo el mismo nombre

Temascrash, physx, diagnóstico, instrumentación

Esta semana publiqué sobre el mod en Reddit. Siete mil visualizaciones, cuarenta y cinco votos: nada mal. Pero lo que de verdad saqué fue un comentario que me decía dónde guarda Cyberpunk sus informes de crash. Una carpeta oculta, un directorio por crash, y en cada uno un volcado de memoria y tres archivos de texto plano. Llevaba días adivinando la causa de los crashes mientras, después de cada uno, me esperaba un informe.

Había cincuenta y seis, desde el 17 de agosto. Leerlos me llevó una tarde y un script pequeño, y lo primero que dijeron fue que estaba persiguiendo un problema que en realidad eran dos. No se superponen ni un segundo. Uno mata el juego entre quince y cuarenta y siete segundos después de arrancar, con unos seiscientos megabytes de memoria de video en uso. Eso es el menú principal, no una ciudad cargada, y ninguno de los sistemas del mod empezó a correr todavía. El otro lo mata en algún momento entre los dos y los veintitrés minutos, con cuatro gigabytes o más. Cada crash de la pila cae limpiamente en uno o en otro.

El temprano son treinta y ocho de los cincuenta y seis, y no es nuestro. Es siempre el mismo fallo del driver de video, en la misma dirección de memoria, y la prueba que por fin me convenció vino de afuera del juego. Windows lleva su propio registro de fallos de driver, y cincuenta y seis de sus cincuenta y siete entradas caen en los noventa segundos previos a uno de estos crashes. Ningún script que yo pueda escribir llega hasta ese registro. Tampoco sigue el ritmo del trabajo: el día de sesenta commits y veinticuatro arranques no tuvo ninguno de estos crashes, y un día sin un solo commit tuvo siete.

Quedan cuatro crashes que sí son nuestros, todos en el motor de física, y ahí la cosa dejó de ser solo ordenada y se puso interesante. Cuatro crashes, cuatro lugares distintos del código de física, cuatro direcciones basura distintas. Si estuviéramos calculando mal un índice, fallaría siempre en el mismo lugar. Cuatro lugares distintos significan que la lista que recorre el motor de física tiene algo muerto adentro: le estamos sacando un auto de abajo a la física mientras la física todavía lo está leyendo.

El número que lo cerró era uno que llevaba toda la semana imprimiendo sin mirarlo ni una vez. Cada línea de traza que escribimos lleva el ID del hilo que la escribió, el carril de trabajo en el que corrió, y cada carpeta de crash lleva el nombre del hilo que murió. Era el mismo hilo. Las partes de nuestro código que dejamos programadas para correr un instante después se están ejecutando en los hilos de trabajo del propio motor del juego, los mismos que calculan la física. Eso había estado en discusión todo el día. Dejó de estarlo en cuanto esos dos números coincidieron.

El arreglo candidato es pequeño, y se reduce a una pregunta que estaba haciendo mal en seis lugares. Antes de tocar el auto de fuga comprobábamos que siguiera ahí, salvo que la comprobación solo preguntaba si la referencia del script al auto seguía viva. Eso no dice nada sobre si el auto sigue enganchado al mundo, y todo lo que hacemos después toca su cuerpo físico: velocidad, derrape, su lugar en el tráfico. El código del propio juego hace esa segunda pregunta antes de tocar nada. Ahora nosotros también, en los seis.

Está desplegado y nadie jugó todavía ni una partida con él. Si el crash vuelve con esto puesto, la teoría muere, y dejo de adivinar qué sistema cancela la orden de fuga para ir a preguntárselo directamente al motor del juego. Que, por lo visto, me lo dice si me engancho en el lugar correcto.