- Se confirmó un fenómeno de crash del juego causado por un overflow de variable en el motor de DOOM
- Se realizó un experimento de ejecutar DOOM durante 2.5 años en un entorno de uso real
- A medida que el valor de la variable seguía aumentando, llegó al overflow y el juego se cerró en el momento esperado
- El experimento se llevó a cabo en un entorno de ejecución automática de largo plazo usando una PDA y un UPS casero
- Esta prueba demuestra que un problema teórico también puede ocurrir realmente en la práctica
Antecedentes y motivación del experimento
- Hace unos dos años y medio, al leer un texto sobre la estructura y el funcionamiento del motor de DOOM, se descubrió que una variable usada para rastrear la ejecución de demos seguía aumentando cada vez que comenzaba una demo
- Aunque esta variable se compara con su valor anterior, al crecer repetidamente incorpora finalmente un riesgo de overflow
- En un entorno de uso normal es difícil llegar a esa situación de overflow, pero se decidió hacer un experimento para comprobar cuánto tiempo tomaría realmente
Método y proceso del experimento
- Mediante un cálculo simple, se estimó que serían necesarios unos 2.5 años de tiempo de ejecución para que ocurriera el overflow
- Para comprobarlo en la práctica, se instaló DOOM en un dispositivo PDA y se le suministró energía con un UPS casero usando baterías 18650
- El dispositivo se conectó al puerto USB del router para mantener de forma continua una alimentación de 5V
- Tras configurar el sistema para que siguiera funcionando en un entorno de carga automática, se lo dejó desatendido la mayor parte del tiempo
Ocurrencia del crash y resultados
- Aproximadamente dos años y medio después de iniciar el experimento, se confirmó la aparición de una notificación emergente en la pantalla del dispositivo
- DOOM pasó, tal como se esperaba, a un estado de crash duro causado por overflow
- El resultado del experimento demuestra que el cierre del juego por overflow de variable también ocurre en hardware real y en un entorno de software real
Conclusión e implicaciones
- Se subraya la importancia de prestar atención a las variables que se acumulan y aumentan durante largos periodos en programación
- Se comprobó experimentalmente que un problema de overflow que parecía solo teórico puede estallar en el mundo real
- Esto sirve como advertencia sobre fallas ocultas en código legado o en software que funciona durante largos periodos
1 comentarios
Opiniones de Hacker News
Hace como un año, mientras revisaba el sistema de temporizador de Crash Bandicoot, descubrí que en Crash 3 un valor de tipo int32 sigue aumentando constantemente; la estructura hace que solo se reinicie al morir. Si lo dejas encendido 2.26 años, ocurre un overflow. En ese momento el tiempo se vuelve "negativo" y el juego se rompe de varias maneras graciosas. Hice un video sobre eso: enlace de YouTube
En Final Fantasy 9, para obtener cierta arma tienes que llegar a una zona avanzada en menos de 12 horas (10 horas en la versión europea), pero por un bug también se puede conseguir si dejas el juego encendido durante 2 años hasta que el temporizador haga overflow. Incluso esperando con calma se logra el objetivo. Enlace con explicación detallada
Me sorprende que en tu video no hayas hecho ni una sola broma con la palabra "crash". Incluso podrías haber llamado "crash" a un freeze; me faltó un poco eso.
Me da curiosidad si era común usar signed integer por defecto para llevar temporizadores. Si hubiera sido unsigned, el tiempo hasta el overflow se habría duplicado; me pregunto por qué eligieron eso.
Creo que muchos juegos estaban hechos así. SotN también tiene un temporizador global. En sistemas de 32 bits, para juegos que se usaban unos meses o, como mucho, unos años, no sentían la necesidad de probar el paso de varios años. En esa época nadie imaginaba que el software que hacía iba a ser hackeado, analizado y sometido a ingeniería inversa. Nosotros tampoco solemos pensar mucho en eso cuando programamos normalmente.
El verdadero desbloqueo de Time Twister.
Suena como una situación que sí podría hacer que el juego se sienta injugable. Ojalá alguien lo arregle. Doom es un juego realmente excelente y siempre vuelvo a él cada ciertos años. El reboot de 2016 también fue divertido, pero los títulos posteriores personalmente no me gustaron mucho.
Hay una comunidad para la gente que prefiere el estilo de gameplay del Doom clásico: r/boomershooters
Yo igual. El diseño tipo metroidvania y la estructura de hub central en los títulos recientes no me dan esa sensación de antes. Me gusta más el progreso simple de correr, matar enemigos, encontrar secretos y pasar al siguiente nivel.
A mí también me pasa, especialmente me encanta el modo brutality.
Dato interesante: ahora Doom es propiedad de Microsoft junto con Quake, StarCraft, WarCraft, Overwatch, todos los juegos de aventura de Infocom y Sierra, y también Halo. Microsoft lleva intentando quedarse con la mayoría de la propiedad intelectual de los juegos de PC desde 1996, así que casi logró su objetivo.
El de 2016 es el mejor FPS para un jugador que he probado. Lo único comparable para mí fue Titan Fall 2.
Me pregunto si el hardware tiene alguna función para atrapar overflows. Leí un texto sobre cómo funciona el motor de Doom y vi que la variable de seguimiento de demos sigue aumentando incluso cuando empieza la siguiente demo. Esa variable se compara con una segunda variable que guarda el valor anterior. Me intriga por qué exactamente el juego real terminó crasheando.
Hay que agradecer que ya sabían de antemano cuál era la causa del bug. También pudo haber pasado que, después de 2.5 años, alguien dijera: "carajo, se me olvidó activar el log de depuración".
DOOM se cayó antes que Windows CE.
Lo que más me impresiona es que una aplicación haya seguido corriendo 2.5 años en una PDA. Dudo muchísimo que algo así sea posible hoy en hardware moderno, y más aún sin conexión a internet.
De verdad es un récord impresionante.
Parece que el sitio se cayó por demasiado tráfico, así que dejo un enlace de archive.org: enlace a la copia en archive.org. Lamentablemente no se conservó todo el formato del sitio, pero el texto sí quedó.
2038 parece que va a ser un año interesante.
Mucha gente pasa por alto el problema de NTP de 2036. Ahí es cuando realmente empieza la fiesta.
El 2038 se siente muchísimo más cerca que la época del y2k.
Quedan 13 años para actualizar a int de 64 bits o cambiar
time_ta tipo long long. Muchos equipos embebidos o sistemas cerrados sin soporte van a necesitar atención especial. El OpenFirmware de un SunServer 600MP que usaba antes tenía el mismo problema. Por suerte, ya no es algo de lo que tenga que preocuparme.Resolver ese problema es mi plan de retiro.
Ningún tester que yo conozca haría pruebas a este nivel. Incluso en el sistema donde trabajo, ayer mismo tuve que esperar más de 5 veces para verificar el manejo de errores después de un timeout de 30 segundos, y fue desesperante.
Hace tiempo Windows NT 4 también tenía un bug parecido. Era un contador de alta precisión que medía el uptime del sistema. Antes de Service Pack 3 (o 2), reiniciábamos el sistema con el programador el día 1 de cada mes. Si no, se caía después de unas 42 días de uptime. Ni siquiera Microsoft pensaba que un sistema operativo de servidor fuera a quedarse corriendo tanto tiempo.
Mis respetos otra vez para el equipo de id Software. Si se hubiera desarrollado con las prácticas comunes de hoy, probablemente habría muerto antes de llegar a los 2 años por fragmentación de memoria o memory leaks.