Con difficoltà. Già, il codice che hai scritto non ha un comportamento definito da ; non ti è permesso uscire in un flusso in un gestore di segnali; per questo, non sei autorizzato a chiamare exit
neanche. (Sto basando mie asserzioni qui sullo standard Posix. In puro C++, tutti i sei permesso di fare è assegnare a una variabile di tipo sig_atomic_t
.)
In un caso semplice come il tuo codice, si potrebbe fare qualcosa di simile:
sig_atomic_t stopFlag = 0;
void
handler(int)
{
stopFlag = 1;
}
int
main()
{
signal(SIGINT, &handler);
A a;
while (stopFlag == 0) {
}
std::cout << "will exit..." << std::endl;
return 0;
}
a seconda dell'applicazione, si può essere in grado di fare qualcosa di simile, controllando il stopFlag
in luoghi appropriati.Ma in generale, se provi a fare questo, ci saranno le condizioni della gara: controlli stopFlag
prima del avviando una chiamata di sistema interrotta, quindi esegui la chiamata; il segnale arriva tra il controllo e la chiamata, si effettua la chiamata e non è interrotto. (Ho usato questa tecnica, ma in un'applicazione in cui la chiamata di sistema unico interrompibile è stata una presa di corrente letta con un brevissimo timeout.)
Tipicamente, almeno sotto Posix, si finirà per dover creare un filo di comando ; questo può quindi essere utilizzato per chiudere in modo pulito tutti gli altri thread . Fondamentalmente, si avvia impostando la maschera di segnale per bloccare tutti i segnali, quindi nel thread di gestione dei segnali, una volta avviato, impostare per accettare i segnali a cui si è interessati e chiamare sigwait()
. Questo implica, tuttavia, che si eseguano tutte le normali azioni necessarie per uno shutdown pulito dei thread : il thread di gestione del segnale deve conoscere su tutti gli altri thread, chiamare pthread_cancel
su di essi, ecc. E si è il compilatore deve generare il codice corretto per gestire pthread_cancel
o è necessario sviluppare altri mezzi per garantire che tutti i thread siano stati notificati correttamente . (Si potrebbe sperare, oggi, che tutti i compilatori gestiscono pthread_cancel
correttamente, ma non si sa mai,.. Così facendo ha significativa dei costi di esecuzione, e non è di solito necessario)
fonte
2012-03-08 10:25:57
Nota che la risposta "giusta" non è così "banale "come suggeriscono alcune risposte qui sotto. Ad esempio, dovresti considerare l'utilizzo di 'sigaction' intead di' signal'. Inoltre, il motivo principale per non usare 'exit()' in un gestore di segnali asincroni è che è semplicemente [non supportato] (http://pubs.opengroup.org/onlinepubs/009604599/functions/xsh_chap02_04.html#tag_02_04) . Allo stesso modo per usare 'iostreams' nel gestore del segnale (non ne sono sicuro al 100%). Quindi, usare un semplice 'bool' invece di' volatile std :: sig_atomic_t' potrebbe non essere affidabile o causare un comportamento indefinito. –
http://ppst.me/5cUMeA ha scritto questo piccolo trucco per te, trovo molto più pulito dell'utilizzo di una variabile globale per tenere traccia del flusso di esecuzione. –
@refp Il problema è che presenta un comportamento indefinito dappertutto. –