2009-11-23 11 views
16

Ho impostato i punti di interruzione in uscita e _exit e il mio programma (applicazione multithread, in esecuzione su Linux 2.6.16.46-0.12 SLES10), è in qualche modo ancora uscire in un modo che non riesco a trovarel'impostazione di un breakpoint di uscita gdb non funziona?

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

Program exited with code 0177. 
(gdb) 

l'uscita le funzioni risiedono in libc quindi non ci sono problemi di libreria condivisa con carico posticipato. Qualcuno sa di qualche altro innesco misterioso per l'uscita che non può essere catturato?

EDIT: il problema è ora solo accademica. Ho provato il debugging della ricerca binaria, facendo uscire un sottoinsieme delle mie modifiche (il problema è andato via). Dopo averli applicati di nuovo in sequenza, non riesco più a riprodurre il problema, anche con le cose ripristinate allo stato originale.

EDIT2: ho trovato una ragione per questo tipo di errore di recente, che potrebbe essere stata la fonte originale per questo problema. Per ragioni storiche, il nostro prodotto utilizza la flag maligna del linker -Bsymbolic. Tra gli effetti collaterali di questo è che quando un simbolo non è definito, ma chiamato, il runtime linker GLIBC sarà bombardare esattamente in questo modo, e lo si vede nel debugger come un processo terminato con 0177. Quando il linker runtime interrompe in questo modo, io Suppongo che faccia syscall su _exit direttamente (piuttosto che usare la libreria di runtime C exit() o _exit()). Ciò sarebbe coerente con il fatto che non sono riuscito a rilevare ciò con i punti di uscita nel debugger.

risposta

22

Ci sono due ragioni comuni per _exit punto di interruzione per "miss" - sia GDB non ha impostato il punto di interruzione nel posto giusto, o il programma esegue (un equivalente morale di) syscall(SYS_exit, ...)

Cosa fare info break e disassemble _exit dire?

Potrebbe essere possibile convincere GDB per impostare correttamente il punto di interruzione con break *&_exit. In alternativa, GDB-7.0 supporta catch syscall. Qualcosa del genere dovrebbe funzionare (assumendo Linux/x86_64; notare che il ix86 i numeri saranno diversi) a prescindere da come il programma termina:

(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 

Aggiornamento:
Il tuo commento indica che _exit punto di interruzione è impostato correttamente, quindi è probabile che il tuo processo non viene eseguito semplicemente _exit.

Questo lascia syscall(SYS_exit, ...) e un'altra possibilità (che ho perso prima): tutti i thread in esecuzione pthread_exit. È possibile impostare un punto di interruzione su pthread_exit (ed eseguire info thread ogni volta che lo si preme - l'ultimo thread da eseguire pthread_exit causerà la fine del processo).

Edit:

anche la pena notare che è possibile utilizzare i nomi mnemonici, piuttosto che numeri syscall. È possibile anche aggiungere contemporaneamente più chiamate di sistema alla lista cattura in questo modo:

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

Proverò a creare gdb 7 e a vedere cosa mostra. il * e dà lo stesso indirizzo di istruzione:

 (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 
(Sembra una chiamata di sistema abbastanza standard). Penso di aver almeno isolato il cambio di codice che porta a questa misteriosa uscita, ma non capisco ancora i dettagli. –

+2

Sarebbe meglio usare 'catch syscall exit' e' catch syscall exit_group' invece di valori numerici. Ad esempio, sul mio sistema, 'exit' è' [1] 'not' [60] '. – Ruslan

+0

Inoltre, è possibile impostare entrambi contemporaneamente con 'catch syscall exit exit_group'. In effetti, modificandolo ora ... –

1

Impostazione del punto di interruzione su _exit era una buona idea.

Si potrebbe anche provare il collegamento statico, solo per prendere una pila di potenziali complicazioni gdb fuori dal tavolo.

0177 è sospetto, come lo stato di attesa wait(2) ritorni per bambino fermati, ma gdb è la stampa lo stato uscita, che è una cosa diversa, in modo che probabilmente è un argomento vero e uscita.

+0

OP ha detto che ha già punti di interruzione su _exit e exit. Inoltre, 0177 è 127. Come mai sei arrivato da 127 a SIGCHLD? –

+0

Oh, uscita mancata. Ma ho ragione riguardo lo stato di attesa. Ovviamente non sto parlando del numero del segnale, ma lo stato 'wait (2)' ritorna per un processo interrotto. Guardate questo: $ grep IFSTOPPED /usr/include/bits/waitstatus.h '#define __WIFSTOPPED (stato) (((stato) e 0xff) == 0x7f)', AND, '0x7f == 0177'. Ma sono d'accordo che non è quello che sta succedendo qui. – DigitalRoss

1

Potrebbe essere che hai alcuni riferimenti pigri non risolti in qualche libreria condivisa caricato nel processo. Ho esattamente la stessa situazione in cui "qualcuno da qualche parte" ha abbandonato il processo e questo sembra essere un riferimento irrisolto.

Controlla il tuo processo con l'opzione "ldd -r".

Sembra che ld.so o qualsiasi altra cosa faccia risolvere in modo pigro alcuni simboli alla funzione di uscita uniforme (che dovrebbe essere interrotta IMHO).

La mia situazione:

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

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

Ora uscite è apparso quando ho invocato un certo scenario che utilizza la funzione che è stata definita. Usciva sempre con exitcode = 127 e gdb riportava 0177.

+0

Non sembra essere il caso qui. Non ho simboli indefiniti nel nostro eseguibile (non uscire né altro). –

Problemi correlati