2012-01-12 2 views
9

Ho registrato un gestore di segnale nel mio programma. Dopo aver ricevuto un segnale indesiderato (SIGABRT), chiamo "exit (-1)" nel gestore di segnale per uscire dal processo. Ma come notato in poche occasioni, chiama exit() ma non riesce a terminare il processo.Can exit() non riesce a terminare il processo?

Il problema è stato generato in modo casuale e sospetto fortemente sull'esecuzione di exit().

Possono esserci motivi o casi in cui l'exit() può non riuscire a terminare il processo.

Grazie.

+1

Certamente consiglio di cercare un'altra causa per il bug di una funzione come "exit".Quasi sempre, quando pensi che ci sia un bug nel compilatore o nella libreria standard ecc., È il tuo errore che sta causando l'errore. – Shahbaz

+3

@Shahbaz: Mandar non sta chiedendo un bug nell'implementazione, o suggerisce che ne esiste uno. La domanda è se è specificato "exit" per terminare sempre il programma, e la risposta è no (e specialmente non se viene chiamata da un gestore di segnale). –

+0

Perché non impostare il gestore SIGABRT per uscire()? Qualunque altra cosa stiate facendo nel gestore del segnale, fateli in una chiamata atexit(). –

risposta

13

Stai chiamando exit() dal gestore di segnale?

In man 7 signal, sezione funzioni asincrone-signal-safe è possibile vedere tutte le funzioni che sono garantiti per funzionare quando viene chiamato da un gestore di segnale:

una funzione di gestione del segnale deve essere molto attenti, dal momento che l'elaborazione altrove può essere interrotta a qualche punto arbitrario nell'esecuzione del programma. POSIX ha il concetto di "funzione sicura". Se un segnale interrompe l'esecuzione di una funzione non sicura, e il gestore chiama una funzione non sicura, quindi il comportamento del programma non è definito.

POSIX.1-2004 (noto anche come POSIX.1-2001 tecnico Rettifica 2) richiede un'implementazione per garanzia che le seguenti funzioni possono essere chiamate in modo sicuro all'interno di un gestore di segnale:

Non ci si può vedere le funzioni _Exit(), _exit() e abort(), ma in particolare non exit(). Quindi non dovresti chiamarlo da un gestore di segnale.

La cosa brutta è che anche se si chiama una funzione non sicura da un gestore di segnale (printf() qualsiasi?) Funzionerà solo la maggior parte del tempo ... ma non sempre.

+1

Chiamare una funzione non sicura del segnale asincrono da un gestore di segnale è * perfettamente legale * a meno che il segnale non interrompa un'altra funzione non sicura del segnale asincrono. Questo spiega il motivo per cui funziona "la maggior parte delle volte", ma significa anche che è possibile utilizzare le funzioni non sicure del segnale asincrono nei gestori di segnale anche nel codice corretto e robusto se si presta attenzione affinché il gestore di segnale non possa interrompere un segnale non sicuro funzione (ad esempio, lasciando il segnale mascherato la maggior parte del tempo e solo sbloccandolo durante l'esecuzione di chiamate di libreria puramente aritmetiche o asincrone dal segnale come il descrittore di file IO e 'select'). –

+0

@R .. Hai ragione, ovviamente. Ma in pratica è difficile garantirlo, tranne in casi molto particolari. Personalmente trovo molto più conveniente solo per evitare tutte le funzioni non sicure. – rodrigo

+1

Vedi anche: http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html –

3

Sì, ci sono alcune circostanze, come ad esempio:

L'uscita() funzione in primo luogo appello tutte le funzioni registrate da atexit(), in ordine inverso rispetto alla loro registrazione, salvo che viene chiamata una funzione dopo ogni funzione precedentemente registrata che era già stata chiamata al momento della registrazione. Ogni funzione viene chiamata tante volte quante sono state registrate. Se, durante la chiamata a una di tali funzioni, viene effettuata una chiamata alla funzione longjmp() che interromperebbe la chiamata alla funzione registrata, il comportamento non è definito.

Se una funzione registrata da una chiamata a atexit() non viene restituita, le restanti funzioni registrate non devono essere richiamate e il resto dell'elaborazione di uscita() non deve essere completato. Se exit() viene chiamato più di una volta, il comportamento non è definito.

Vedere la pagina POSIX su exit.

Per ulteriori informazioni, allegare un debugger quando si raggiunge la situazione e dare un'occhiata allo stack di chiamate.