Очистите перед закрытием QCoreApplication.
Вопрос
У меня консольная версия QCoreApplication
который имеет таймеры и осуществляет связь через сокеты, а также использует заблокированный мьютекс.
Когда я закрываю приложение вручную, оно выдает ошибку, сообщающую, что какой-то мьютекс заблокирован и время ожидания истекло.Есть ли способ выполнить очистку в консольном приложении, когда пользователь его закрывает?
Решение
Очистка должна выполняться деструкторами и дочерними и родительскими отношениями.
Сделайте свой главный объект (тот, который находится в основном) дочерним элементом QApplication, чтобы он был уничтожен со всеми своими дочерними элементами до того, как будет разрушен QApplication.
Вы уверены, что убили все свои темы?Если это поток с циклом событий, обязательно позвоните QThread::quit()
выйти из цикла событий перед вызовом 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();
}
Другие советы
Оказывается, закрытие приложения командной строки (проверено на Win7 и VS2010) нажатием кнопки «закрыть» (красная кнопка x в строке заголовка) передает STATUS_CONTROL_C_EXIT
сигнал приложению.Все потоки прерываются с помощью этого кода.
Поток «основной поток» (0x980) вышел с кодом -1073741510 (0xc000013a).
Поток «qthread» (0x2388) вышел с кодом -1073741510 (0xc000013a).
Это означает, что нет возможности перехватить это с помощью QCoreApplication::aboutToQuit()
сигнал.
Взгляни на winnt.h
или ntstatus.h
.Это значение, присвоенное манифестной константу STATUS_CONTROL_C_EXIT
.Средство выполнения просто выбирает, чтобы закончить вашу программу с помощью кода, чтобы отметить операцию отмены пользователя.
вы можете подключиться к QCoreApplication::aboutToQuit подайте сигнал и проведите там необходимую уборку.