2009-06-10 14 views
5

Ho uno QCoreApplication basato su console con timer e comunicazione socket e utilizza anche il mutex bloccato.Pulire prima di chiudere QCoreApplication

Quando chiudo l'applicazione manualmente, viene visualizzato un messaggio di errore che indica che alcuni mutex sono bloccati ed è scaduto. C'è un modo per pulire in un'applicazione console quando l'utente lo chiude?

risposta

15

La pulizia deve essere gestita dai distruttori e dalla relazione figlio-genitore.

Crea il tuo oggetto principale (quello principale) figlio di QApplicazione in modo che venga distrutto con tutti i suoi child prima di QApplication.

Sei sicuro di aver ucciso tutti i fili? Se si tratta di un filo con un'eventloop essere sicuri di chiamare QThread::quit() per uscire dalla eventloop prima di chiamare QThread::wait()

È inoltre possibile utilizzare il vuoto QApplication::qAddPostRoutine (QtCleanUpFunction ptr) a fare un po 'di pulizia speciale.

Per eseguire il debug di questi messaggi è possibile utilizzare QtMsgHandler qInstallMsgHandler (QtMsgHandler h) e scrivere il proprio gestore di messaggi per acquisire tali avvisi. Se è possibile simulare il problema, è possibile impostare un punto di interruzione sul messaggio e vedere sullo stack da cui proviene il messaggio.

void debugMessageHandler(QtMsgType type, const char *msg){ 
    if(QString(msg).contains("The message you can see in the console")){ 
     int breakPointOnThisLine(0);  
    } 

    switch (type) { 
     case QtDebugMsg: 
      fprintf(stderr, "Debug: %s\n", msg); 
      break; 
     case QtWarningMsg: 
      fprintf(stderr, "Warning: %s\n", msg); 
      break; 
     case QtFatalMsg: 
      fprintf(stderr, "Fatal: %s\n", msg); 
      abort(); 
    } 
} 

Al fine di pulire con la nave destructor e il bambino-genitore relazione si può prendere il segnale di chiusura console e chiamare QCoreApplication::exit() all'istanza dell'applicazione.

#include <csignal> 
#include <QtCore/QCoreApplication> 
using namespace std; 

struct CleanExit{ 
    CleanExit() { 
     signal(SIGINT, &CleanExit::exitQt); 
     signal(SIGTERM, &CleanExit::exitQt); 
     signal(SIGBREAK, &CleanExit::exitQt) ; 
    } 

    static void exitQt(int sig) { 
     QCoreApplication::exit(0); 
    } 
}; 


int main(int argc, char *argv[]) 
{ 
    CleanExit cleanExit; 
    QCoreApplication a(argc, argv); 
    return a.exec(); 
} 
+0

quasi completo.una volta che hai chiamato exit (0) devi fare il tuo codice di pulizia specifico Qt da qualche parte che non è nel gestore di segnale exitQt(). quindi devi legare il tuo codice di pulizia Qt al segnale aboutToQuit(). il segnale aboutToQuit viene emesso solo quando viene chiamato qApp-> exit (0). –

+2

C++ 11 rende più semplice: 'signal (SIGTERM, [] (int sig) {qApp-> quit();});' – ManuelSchneid3r

+0

Questo non funziona completamente. Ho reso l'oggetto relativo alla pulizia un figlio di QApplication. Il distruttore viene chiamato correttamente quando la finestra viene chiusa normalmente. Ma dopo l'arresto/il logout del sistema, il distruttore figlio QApplication non viene mai chiamato. – galinette

1

è possibile connettersi al segnale QCoreApplication::aboutToQuit e effettuare la pulizia necessaria lassù.

+2

Ciao Daniel, Ho provato questo, ma il punto di interruzione non ha colpito nello SLOT collegato. la documentazione dice che il segnale ToQuit viene emesso quando si esce da QCoreApplication. La chiusura dell'applicazione console richiama quit()? Grazie, Suresh. –

5

Risulta che la chiusura applicazione a riga di comando (controllato su Win7 & VS2010) premendo (pulsante rosso x sulla barra del titolo) 'vicino' passa il segnale STATUS_CONTROL_C_EXIT all'applicazione. Tutti i thread sono stati interrotti con questo codice.

Il filo 'Discussione principale' (0x980) è uscito con il codice di -1.073,74151 milioni (0xC000013A).

Il thread 'QThread' (0x2388) è terminato con il codice -1073741510 (0xc000013a).

Ciò significa che non è possibile intercettarlo con il segnale QCoreApplication::aboutToQuit().

Dai un'occhiata a winnt.h o ntstatus.h. Questo è il valore assegnato alla costante manifestSTATUS_CONTROL_C_EXIT. Il runtime è solo scegliendo di terminare il programma con il codice per annotare l'operazione di annullamento dell'utente .

+0

Usa SetConsoleCtrlHandler() per intercettarli e chiama qApp-> exit (42) – Macke

Problemi correlati