2011-04-28 8 views
6

¿Cuáles son algunos consejos para la depuración difícil de reproducir los errores de concurrencia que sólo suceden, digamos, una vez cada mil ejecuciones de una prueba? Tengo uno de estos y no tengo ni idea de cómo proceder para depurarlo. No puedo poner instrucciones de impresión o relojes de depuración en todo el lugar para observar el estado interno, porque eso cambiaría los tiempos y produciría cantidades abrumadoras de información cuando el error no se reproduzca correctamente.¿Consejos para depurar errores de concurrencia difíciles de reproducir?

+0

¿Es un problema de corrupción de datos (una ubicación de memoria, variable o búfer), o es un problema de llamada a la función (las funciones se llaman fuera de secuencia o en momentos inesperados)? Las técnicas de detección son diferentes. – rwong

+0

@wong: corrupción de datos. – dsimcha

Respuesta

5

Esta es mi técnica: generalmente uso mucho assert() para verificar la consistencia/validez de los datos tan a menudo como sea posible. Cuando una afirmación falla, el programa se bloquea generando un archivo central. Luego uso un depurador con el archivo central para comprender qué configuración de subproceso llevó a la corrupción de datos.

1

Es altamente depende de la naturaleza del problema. Comúnmente útiles son bisección (para reducir el espacio de búsqueda) + código de "instrumentación" con las afirmaciones para acceder a los ID de hilo, bloquear/desbloquear el recuento, el orden de bloqueo, etc., con la esperanza de que cuando el problema se reproducirá la próxima vez que la aplicación o bien se registro un mensaje detallado o será core-dump que le da la solución.

1

Un método para encontrar la corrupción de datos causada por el fallo de concurrencia:

  • agregar un contador atómica para que los datos o tampón.
    • dejar todo el código de sincronización existente como es - no los modifique, en el supuesto de que se va a corregir el error en el código existente, mientras que el nuevo contador atómica se eliminará una vez que el error se corrige.
  • Al comenzar a modificar los datos, incremente el contador atómico. Cuando termine, disminuya.
  • volcado de memoria tan pronto como se entere de que el contador es mayor que uno (el uso de algo similar a InterlockedIncrement)
0

Targeted código de prueba de unidad es lento pero eficaz, en mi experiencia.

Afine el código no lo más que pueda. Escriba un código de prueba que sea específico del código culpable aparente y ejecútelo en un depurador todo el tiempo que sea necesario para reproducir el problema.

2

Esto puede que no te ayude pero probablemente ayude a alguien a ver esta pregunta en el futuro.

Si está utilizando un lenguaje .Net, puede utilizar el proyecto CHESS de investigación de Microsoft. Ejecuta pruebas unitarias con todo tipo de entrelazado de hilos y muestra cuáles causan que ocurra el error.

Puede haber una herramienta similar para el idioma que está utilizando.

+0

El enlace parece roto ahora –

0

Una de las estrategias que uso para simular el intercalado de los hilos es mediante la introducción de espiras. La advertencia es que no debe utilizar los mecanismos estándar de espera de giro para su plataforma, ya que es probable que introduzcan barreras de memoria. Si el problema que está intentando solucionar es causado por la falta de una barrera de memoria (porque es difícil conseguir las barreras correctas cuando se utilizan estrategias de bloqueo), los mecanismos estándar de espera de espionaje simplemente enmascararán el problema. En su lugar, coloque un bucle vacío en los puntos donde desea que su código se bloquee por un momento. Esto puede aumentar la probabilidad de reproducir un error de concurrencia, pero no es una bala mágica.

0

Si el fallo es un callejón sin salida, sólo conectar una herramienta de depuración (como gdb o strace) para el programa después pasa el punto muerto, y observando que cada hilo está atascado, a menudo se puede obtener suficiente información para rastrear el fuente del error rápidamente.

Cuestiones relacionadas