2012-01-15 6 views
11

En los últimos meses he recibido algunos informes de QA sobre la suspensión de uno de nuestros servicios. Al examinar un vuelco colgante usando WinDbg, cada vez que descubrí lo mismo: la sección crítica de bloqueo del cargador está bloqueada pero el hilo propietario no se encuentra por ningún lado. Como el hilo se ha ido y el único rastro que puedo ver es una sección crítica global que dejó atrás, no veo qué código se ejecutó en el subproceso de subproceso, ni siquiera de qué DLL salió ese subproceso, ni siquiera puede ser uno de nuestro (es decir, proveedor de terceros).Buscando ideas para eliminar errores en un gremlin de inicio de servicio de windows complicado

Este problema es muy esporádico, solo se lo ve tal vez 3-4 veces en los últimos 6 meses que ocurren naturalmente en la naturaleza. El resto del tiempo, el servicio funciona perfectamente. Así que esto me hace creer que es una especie de condición de tiempo/carrera.

Recientemente, he decidido encargarme de resolver esto. Configuro una máquina con script WinTask que constantemente inicia/detiene dicho servicio. Una buena noticia es que dentro de 5-6 horas puedo reproducir el problema.

Ahora para la siguiente parte: ¿cómo lo aíslo?

Esto es lo que he probado hasta ahora:

  1. campo utilizado "depurador" en la configuración de la imagen gflags para ejecutar el servicio bajo automagicamente cdb cada vez que se inicia. Hasta ahora, esto ha estado funcionando durante dos días y nunca se colgó, por lo que estoy pensando en que el depurador introdujo lo suficiente de un cambio de tiempo para que el problema sea invisible.

  2. Verificador de aplicación descargado y configurado el proceso para ejecutar con eso. Se ha encontrado un error completamente no relacionado donde creamos la variable temporal CComBSTR, la asignamos a un VARIANT y pasamos la variante a una llamada de función aunque CComBSTR eliminó por mucho tiempo la cadena asignada en ese punto. No crea que este error esté relacionado porque la cadena es de solo lectura y el hilo en el que se ejecuta no es el que está muriendo.

Estoy haciendo esta publicación en caso de que se les ocurra algo que no estoy considerando.

Pensé que había una utilidad de Windows que cargaba artificialmente la CPU e hizo otras cosas para hacer aparecer las condiciones de carrera y pensé que el verificador de aplicaciones hizo eso, pero aparentemente no es así. ¿Alguien sabe por lo que estoy hablando, o simplemente lo soñé?

A menos que algo sucede durante el fin de semana mi próximo paso sería desactivar todos los depuradores, volver a la acción y cortar uno de DllMains para registrar eventos/THREAD_DETACH THREAD_ATTACH. Al menos podré interceptar el hilo que está muriendo cuando se crea. Eso podría arrojar algo de luz.

+1

-1 ?? ¿¿por qué?? ¿No mostré suficiente detalle? ¿Parece que no hice suficiente investigación? ¿Las personas no preguntan a stackoverflow cuando se quedan perplejos ante los problemas de desarrollo de software? – DXM

+0

Sí, esta es una pregunta perfectamente válida. Lo único que lo haría mejor sería publicar algún código. Supongo que esa es la razón por la que alguien pasó volando. –

+2

Es una aplicación de producción que ha estado en el mercado por más de 10 años. Ni siquiera sé qué DLL está causando el problema, y ​​mucho menos publicar código de empresa de código cerrado en línea, incluso si pudiera copiar/pegar 5 millones de líneas de código fuente. No tengo idea de qué fue lo que cambió, pero la primera vez que vi el problema fue hace 6 meses. – DXM

Respuesta

2

Algo que podría intentar es adjuntar un depurador de kernel, luego ejecutar el proceso en Appilcation Verifier. AV tiene comprobaciones para descargar un archivo DLL mientras contiene un CS y termina los hilos que todavía tienen CS. Entonces, esos puntos de interrupción deberían activarse en el depurador del kernel y, con suerte, se puede atrapar en el acto. Ejecutarlo bajo el KD con suerte no ralentizará como lo hace el depurador de modo de usuario.

+0

kernel depurador ... interesante. Es un reino en el que nunca me he aventurado. Podría ser una opción si todo lo demás falla. De esta forma puedo tener el depurador ejecutándose y monitoreando cosas mientras el servicio se inicia y se detiene. Necesitaré una segunda máquina para esto, ¿verdad? ¿También necesito un cable de serie o tienen otros medios en estos días? – DXM

+0

la manera más fácil es en una máquina virtual, y luego la VM exporta el puerto COM como un conducto con nombre que windbg sabe cómo conectarse. – jcopenha

+0

Estoy tratando de no respirar en esta máquina más de lo necesario. VM podría asustar a este error al igual que lo hizo cdb. Entonces, suponiendo que lo deje donde está, cable de serie, ¿verdad? – DXM

0

Algunas ideas aleatorias: si adjuntar un depurador no ayuda, entonces la instrumentación (su último punto) es el siguiente paso. Pero, ¿cómo puede un hilo simplemente morir sin derribar todo el proceso, estás atrapando excepciones en alguna parte? Es posible que desee iniciar sesión allí también. También puede configurar WinDbg para romper con todas las excepciones de primera oportunidad, si eso ayuda. La ventana de salida de WinDbg mostrará excepciones de primera oportunidad de todos modos, incluso si no se rompe.

+0

solo ocurre en el arranque y muy infrecuentemente, así que no puedo tener conectado windbg. Pero esto es exactamente lo que intento lograr con cdb, que es una versión de consola del mismo motor de depuración. Definitivamente tenemos iniciar sesión en los hilos que controlamos, pero sé que otras API/DLL comienzan sus propios hilos y no tengo idea de lo que están haciendo. Cosas divertidas. – DXM

0

Probaría un depurador no invasivo, y vea cómo va eso, aunque no podrá detener el proceso, debería poder ver cualquier mensaje de depuración así como cualquier conversación que se inicie y se detenga, y debe tener un impacto mínimo en el rendimiento del proceso. Normalmente utilizo windbg para mi depuración, pero creo que cbd también tiene opciones similares. Es muy probable que esto le permita ver lo que sucede en el proceso y, al menos, comenzar a ayudar a reducirlo. Una cosa que quizás quieras asegurarte es redirigir la salida (.logopen en windbg) para asegurarte de que nada salga de tu buffer.

+0

¿qué quiere decir con depurador no invasivo? WinDbg y cdb son esencialmente el mismo depurador. WinDbg tiene UI, cdb es consola, pero en todos los demás aspectos son idénticos. Hice que mi servicio comenzara en cdb, que abrió un puerto tcp para poder usar windbg para conectarme más tarde. Además, como mencionaste, utilicé .logopen para asegurarme de que sea lo que sea que vea cdb, también pude ver a través de un archivo de registro. – DXM

+0

utilice el comando -pv para que cdb se una de forma no invasiva. No podrá detener los hilos ni realizar ninguna acción real, pero debería poder ver más información de diagnóstico y, con suerte, no causar problemas de rendimiento que impidan que se produzca el problema. Aquí hay un enlace sobre depuración no invasiva http://msdn.microsoft.com/en-us/library/ff552274(v=vs.85).aspx – Zipper

1

Así resulta que estaba más cerca de la solución de lo que me di cuenta. Con el servicio ejecutándose bajo cdb, que alteró el tiempo y luego lo ejecutó con el verificador de aplicaciones, lo que alteró aún más el tiempo (el montón de páginas habilitado hace que la asignación sea más lenta), el ingrediente secreto que me faltaba era prime95.exe. Ejecutar prime95.exe por encima de la prioridad normal, realmente arruinó el tiempo que intentaba no cambiar, pero hizo que el problema apareciera en menos de 15 minutos.

La causa:

tercera parte del SDK para la adquisición de datos de tarjetas de hardware. Cuando nuestro servicio se inicie, consultaremos diferentes componentes de captura para sus capacidades. Una vez realizada la consulta, lanzamos la instancia del componente. Aparentemente esta DLL comenzó un hilo separado, que adquirió un bloqueo de cargador y luego procedió a hacer un montón de inicialización en ese hilo. Si durante ese tiempo, nuestra consulta de capacidad se hizo y liberamos el componente, su código llamaría TerminateThread() en este otro hilo, dejando el bloqueo del cargador permanentemente bloqueado. Prime95 ralentizó todo abajo lo suficiente para mí para coger esta condición de carrera y sale el siguiente mensaje de detención verificador:

======================================= 
VERIFIER STOP 00000200: pid 0x1A8C: Thread cannot own a critical section. 

0000091C : Thread ID. 
77E17340 : Critical section address. 
00000000 : Critical section debug information address. 
00000000 : Critical section initialization stack trace. 

parte divertida es que este hilo se "desaparece" sin excepción de ningún tipo, por lo que no lo haría depurador incluso tomar la primera oportunidad de nada. ¿Quién usa TerminateThread ????

Gracias a todos por sus sugerencias y asistencia. De hecho, estaba empezando a esperar conducir a Radioshack durante el almuerzo para comprar un cable serie y luego pasar unos días jugando con KD. Parece que tendrá que esperar hasta la próxima :)

Cuestiones relacionadas