2009-06-10 5 views
5

У меня есть консольный QCoreApplication, который имеет таймеры и выполняет связь сокетов, а также использует заблокированные мьютексы.Очистка перед закрытием QCoreApplication

Когда я закрываю приложение вручную, он дает ошибку, говоря, что какой-то мьютекс заблокирован и он отключен. Есть ли способ, который я могу очистить в консольном приложении, когда пользователь его закрывает?

ответ

15

Очистка должна обрабатываться деструкторами и отношениями между родителями и родителями.

Сделайте свой главный объект (основной) дочерним элементом QApplication, чтобы он был разрушен всеми его дочерними элементами до QApplication.

Вы уверены, что убили все свои темы? Если нить с eventloop обязательно позвоните QThread::quit(), чтобы выйти из eventloop перед вызовом QThread::wait()

Вы также можете использовать вакуум QApplication::qAddPostRoutine (QtCleanUpFunction ptr) сделать некоторые специальные очистки.

Для отладки этих сообщений вы можете использовать QtMsgHandler qInstallMsgHandler (QtMsgHandler h) и написать свой собственный обработчик сообщений, чтобы зафиксировать эти предупреждения. Если вы можете имитировать проблему, вы можете установить точку останова в сообщении и увидеть в стеке, откуда приходит сообщение.

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(); 
    } 
} 

Для того, чтобы очистить с деструктор и ребенок-родитель отношения корабля вы можете поймать близкий сигнал консоли и вызвать QCoreApplication::exit() к экземпляру приложения.

#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

почти совершенно.после того, как вы вызвали exit (0), вы должны сделать свой Qt-код для очистки где-то, что отсутствует в обработчике сигнала exitQt(). поэтому вам нужно связать код очистки Qt с сигналом aboutToQuit(). сигнал aboutToQuit выдается только после вызова qApp-> exit (0). –

+2

C++ 11 упрощает процесс: 'signal (SIGTERM, [] (int sig) {qApp-> quit();});' – ManuelSchneid3r

+0

Это не работает полностью. Я сделал объект, связанный с очисткой, дочерним элементом QApplication. Деструктор правильно вызывается, когда окно нормально закрывается. Но после выключения/выхода из системы дочерний деструктор QApplication никогда не вызывается. – galinette

1

вы можете подключиться к сигналу QCoreApplication::aboutToQuit и выполнить необходимую очистку там.

+2

Hi Daniel, Я пробовал это, но точка останова не попала в подключенный SLOT. документация говорит, что сигнал оToQuit испускается при выходе из QCoreApplication. Закрывает ли консольное приложение quit()? Thanks, Suresh. –

5

Оказывается, что закрытие приложение командной строки (проверено на Win7 & VS2010), нажав «закрыть» (красный х кнопку на строке заголовка) передает сигнал STATUS_CONTROL_C_EXIT к приложению. Все потоки прерываются с помощью этого кода.

Нить 'Главный поток' (0x980) завершился с кодом -1073741510 (0xC000013A).

Поток «QThread» (0x2388) вышел с кодом -1073741510 (0xc000013a).

Это означает, что невозможно перехватить это с помощью сигнала QCoreApplication::aboutToQuit().

Посмотрите на winnt.h или ntstatus.h. Это значение, присвоенное константе манифольда STATUS_CONTROL_C_EXIT. Время выполнения - это только , выбрав для завершения вашей программы код, чтобы отметить отмену пользователя .

+0

Используйте SetConsoleCtrlHandler() для их перехвата и вызовите qApp-> exit (42) – Macke