Вопрос

I am currently adding a functionality to my app that would allow it to restart.

This is what the main looks like

int main(int argc, char *argv[])
{
    const int RESTART_CODE = 1000;
    int return_from_event_loop_code;
    QPointer<QApplication> app;
    QPointer<foo> main_window;
    do
    {
        if(main_window)
            delete main_window; 
        if(app) 
            delete app;

            app = new QApplication(argc, argv);
            main_window = new foo();
            main_window->show();
            app->setActiveWindow(main_window);

            return_from_event_loop_code = app->exec();
    } 
    while(return_from_event_loop_code==RESTART_CODE);

  return return_from_event_loop_code;
}

Now the first time runs fine however when the application is restarted using the RestartApp method mentioned below . The get method of QNetworkAccessManager returns the lock error. This is what my code looks like

void foo::MethodA()
{
    ....
    ....
    QUrl url("some url");
    QNetworkRequest request;
    request.setUrl(url);
    networkManager = new QNetworkAccessManager(this);
    QObject::connect(networkManager, SIGNAL(finished(QNetworkReply*)),this, SLOT(replyFinished(QNetworkReply*)),static_cast<Qt::ConnectionType>(Qt::QueuedConnection | Qt::UniqueConnection));
    currentReply = networkManager->get(request); //Crashes when the app is restarted again
    connect(currentReply, SIGNAL(error(QNetworkReply::NetworkError)),this, SLOT(slotNetworkError(QNetworkReply::NetworkError)),Qt::UniqueConnection);
}

//Slot
void foo::replyFinished(QNetworkReply* rply)
{
    ....
    .....
    rply->deleteLater();
}

//Slot
void foo::RestartApp()
{
    QCoreApplication::exit(1000);
}

Now here is what happens when the app starts for the first time everything is fine. However when the RestartApp method is called and return_from_event_loop_code = app->exec(); method in main is called again this time at the statement currentReply = networkManager->get(request); in MethodA the app crashes and ends up in

mlock.c

void __cdecl _unlock (
        int locknum
        )
{
        /*
         * leave the critical section.
         */
        LeaveCriticalSection( _locktable[locknum].lock );
}

Any idea on why the app crashes on the get statement of QNetworkAccessManager when the app is given the instruction to restart ?

Это было полезно?

Решение

I've done some investigation on the crash. It's indeed caused by destruction of QApplication. QNetworkAccessManager internally uses a QNetworkConfigurationManagerPrivate object. This object is created when needed and used until the application finishes. The qNetworkConfigurationManagerPrivate function is used to create or get existing object.

When QApplication is destroyed, it executes all post routines, including connManager_cleanup. This function indirectly destroys QNetworkConfigurationManagerPrivate object and sets appShutdown local flag. When this flag is set, qNetworkConfigurationManagerPrivate function will not create new QNetworkConfigurationManagerPrivate objects anymore. So after destruction of QApplication QNetworkAccessManager becomes non-functional.

I thought it's a misuse of QApplication object, but recently I found a proof link that the use is correct.

Qt's Coding Conventions state:

Q[Core]Application is a singleton class. There can only be one instance at a time. However, that instance can be destroyed and a new one can be created.

So this issue should be considered a Qt bug.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top