2009-11-23 13 views
16

he establecido puntos de interrupción en la salida y _exit y mi programa (aplicación multiproceso, que se ejecuta en Linux 2.6.16.46-0.12 SLES10), es de alguna manera todavía salir de una manera que no puedo localizarconfigurando un punto de interrupción de salida de gdb no funciona?

 
(gdb) c 
... 
[New Thread 47513671297344 (LWP 15279)] 
[New Thread 47513667103040 (LWP 15280)] 
[New Thread 47513662908736 (LWP 15281)] 

Program exited with code 0177. 
(gdb) 

la salida las funciones residen en libc, por lo que no hay problemas de biblioteca compartida de carga diferida. ¿Alguien sabe de algún otro disparador misterioso para la salida que no se puede atrapar?

EDITAR: el problema ahora es solo académico. Probé la depuración de búsqueda binaria, anulando un subconjunto de mis cambios (el problema desapareció). Después de aplicarlos de nuevo en secuencia, ya no puedo reproducir el problema, incluso con las cosas restauradas al estado original.

EDIT2: Encontré una razón para este tipo de error recientemente, que puede haber sido la fuente original de este problema. Por razones históricas, nuestro producto usa el indicador linker maligno -Bsymbolic. Uno de los efectos secundarios de esto es que cuando un símbolo no está definido pero se llama, el enlazador de tiempo de ejecución de GLIBC bombardeará exactamente de esta manera, y lo verá en el depurador como un proceso salido con 0177. Cuando el enlazador de tiempo de ejecución aborta de esta manera, Supongo que hace que syscall salga directamente (en lugar de utilizar la salida de la biblioteca C runtime() o _exit()). Eso sería coherente con el hecho de que no pude detectar esto con los puntos de interrupción de salida en el depurador.

Respuesta

22

Hay dos razones comunes para _exit punto de interrupción a "miss" - ya sea GDB no ha ajustado el punto de interrupción en el lugar correcto, o el programa realiza (un equivalente moral de) syscall(SYS_exit, ...)

Qué hacer info break y disassemble _exit dice?

Puede convencer GDB para establecer el punto de interrupción correctamente con break *&_exit. Alternativamente, GDB-7.0 es compatible con catch syscall. Algo como esto debería funcionar (suponiendo Linux/x86_64; en cuenta que en ix86 los números serán diferentes), independientemente de la forma en que el programa termine:

(gdb) catch syscall 60 
Catchpoint 3 (syscall 'exit' [60]) 
(gdb) catch syscall 231 
Catchpoint 4 (syscall 'exit_group' [231]) 
(gdb) c 

Catchpoint 4 (call to syscall 'exit_group'), 0x00007ffff7912f3d in _exit() from /lib/libc.so.6 

Actualización:
su comentario indica que _exit punto de interrupción se establece correctamente, así que es probable que su proceso simplemente no ejecuta _exit.

Eso deja syscall(SYS_exit, ...) y otra posibilidad (que me perdí antes): todos los hilos que ejecutan pthread_exit. Es posible que desee establecer un punto de interrupción en pthread_exit también (y ejecutar info thread cada vez que lo pulse; el último subproceso para hacer pthread_exit hará que el proceso finalice).

Editar:

También digno de mención que se puede utilizar nombres mnemotécnicos, en lugar de números de llamadas al sistema. También puede agregar simultáneamente múltiples llamadas al sistema a la lista de capturas de este modo:

(gdb) catch syscall exit exit_group 
Catchpoint 2 (syscalls 'exit' [1] 'exit_group' [252]) 
+0

Intentaré construir gdb 7 y veré lo que muestra. el * y da la misma dirección de la instrucción:

 (gdb) b _exit Breakpoint 2 at 0x2aeea040f250 (gdb) b *&_exit Note: breakpoint 2 also set at pc 0x2aeea040f250. Breakpoint 3 at 0x2aeea040f250 
 0x00002aeea040f250 <_exit+0>: mov %fs:0x0,%r9 ... 0x00002aeea040f275 <_exit+37>: syscall 
(Parece que una llamada al sistema bastante estándar). Creo que al menos he aislado el cambio de código que lleva a esta salida misteriosa, pero aún no entiendo los detalles. –

+2

Sería mejor utilizar 'catch syscall exit' y' catch syscall exit_group' en lugar de valores numéricos. En mi sistema, por ejemplo, 'exit' es' [1] 'not' [60] '. – Ruslan

+0

Además, puede configurar ambas cosas a la vez con 'catch syscall exit exit_group'. De hecho, edítelo ahora ... –

1

Configurar el punto de interrupción en _exit fue una buena idea.

También puede intentar vincular estáticamente, solo para sacar de la mesa una serie de posibles complicaciones de gdb.

0177 es sospechosamente a la situación de espera wait(2) devoluciones para niño dejó, pero GDB es imprimir el estado de salida , que es una cosa diferente, por lo que es probable que haya un argumento de salida real.

+0

OP dijo que ya tiene puntos de interrupción en _exit y exit. Además, 0177 es 127. ¿Cómo demonios llegaste de 127 a SIGCHLD? –

+0

Oh, se perdió la salida. Pero tengo razón sobre el estado de espera. Obviamente no estoy hablando del número de señal, pero el estado 'wait (2)' regresa para un proceso detenido. Mira esto: $ grep IFSTOPPED /usr/include/bits/waitstatus.h '#define __WIFSTOPPED (estado) (((estado) & 0xff) == 0x7f)', AND, '0x7f == 0177'. Pero estoy de acuerdo en que eso no es lo que está sucediendo aquí. – DigitalRoss

1

Podría ser que usted tiene algunas referencias perezosos sin resolver de alguna librería compartida cargado en proceso. Tengo exactamente la misma situación que "alguien en alguna parte" salió del proceso y esa parecía ser una referencia no resuelta.

Compruebe su proceso con la opción "ldd -r".

Parece ld.so o lo que sea, la resolución perezosa de algunos símbolos para la función de salida uniforme (que debe cancelarse en mi humilde opinión).

Mi situación:

$ ldd ./program 
undefined symbol: XXXX (/usr/lib/libYYY.so) 

$./program 
program: started! 
... 
<program is running regardless of undefined references> 

Ahora sal apareció cuando he invocado algún escenario que utiliza función que no estaba definido. Siempre salió con exitcode = 127 y gdb informó 0177.

+0

Ese no parece ser el caso aquí. No obtengo símbolos indefinidos en nuestro ejecutable (ni salida ni nada). –

Cuestiones relacionadas