OpenAI corrige condición de carrera GNU libunwind de 18 años mediante debug 'epidemiológico'
Ingenieros de OpenAI debuguearon y corrigieron una condición de carrera de 18 años en la función _Ux86_64_setcontext de GNU libunwind que estaba causando crashes misteriosos en Rockset, el servicio de infraestructura de datos C++ que alimenta los plugins de búsqueda y datos de ChatGPT. El avance no vino de analizar casos de crash individuales—que presentaban síntomas contradictorios—sino de aplicar 'debugging epidemiológico': construir un pipeline para analizar automáticamente cada core dump de producción del año pasado, luego buscar patrones a nivel de población. El equipo tuvo a ChatGPT escribir un script que extrajo registros de cada archivo core, filtró falsos positivos conocidos y etiquetó crashes como return-to-null, misaligned-stack u otro, ejecutándose en paralelo en un año de dumps de Rockset.
Lo que parecía ser un bug resultó ser dos: corrupción de hardware (un único host físico de Azure produciendo silenciosamente resultados de CPU incorrectos) y una genuina condición de carrera libunwind. La causa raíz en libunwind: durante el unwinding de excepción C++, la función actualiza el stack pointer (%rsp) antes de terminar la lectura del instruction pointer del struct en el stack antiguo. Si llega una señal en esa ventana de picosegundos—aproximadamente 100 picosegundos a velocidades de reloj modernas—el kernel construye su marco de señal en la parte superior del struct, corrompiendo el instruction pointer. Rockset de OpenAI usa señales SIGUSR2 cada pocos milisegundos para contabilidad por query, creando muchos más eventos de entrega de señal que aplicaciones típicas y convirtiendo una carrera teóricamente posible en un crash de producción. La corrección reordena instrucciones para que %rip se lea antes de que se actualice %rsp, eliminando completamente la ventana de carrera. OpenAI enviación la corrección y el reproductor a GNU libunwind.
Para profesionales debugueando crashes de producción con síntomas contradictorios: este caso de estudio demuestra que 'datos completos y etiquetados en toda la población de fallas' es más rápido que análisis más profundo de casos individuales. La conclusión del equipo: 'El paso más importante no fue la lectura inteligente de ensamblador o el conocimiento profundo de los detalles. Fue construir un conjunto de datos de alta calidad.' La observación a nivel de población reveló lo que el razonamiento caso por caso no pudo: dos fenómenos no relacionados siendo confundidos. Busque este patrón en su propio análisis de incidente y considere si su registro y captura de crashes permiten debugging a nivel de población.
Fuentes
- Primary source
- infoq.com
“OpenAI engineers spent weeks trying to explain mysterious crashes in Rockset, discovering a race condition in GNU libunwind's _Ux86_64_setcontext function”
- infoq.com
“The breakthrough came not from deeper inspection of individual crashes but from switching to epidemiological debugging”
- infoq.com
“The root cause was a race condition in GNU libunwind's _Ux86_64_setcontext function that had been present for 18 years”