peniwize / GatHost

Game authentication terminal (GSA GAT) protocol host application, written in C++ on Qt 5.x.
http://youtu.be/6oq23HQIX-c
GNU General Public License v3.0
0 stars 0 forks source link

Assert failure in QCoreApplication::sendEvent #1

Open IG0111 opened 6 years ago

IG0111 commented 6 years ago

Hello, i have build application on windows 7 with qt v.5.10.0. Works fine except when program receiving special functions response from EGM exception occur(most of the time not always):

Assert failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread. Current thread 0x0x39bd40. Receiver '' (of type 'GatSpecialFunctionExec') was created in thread 0x0x14f3a8", file kenrel\qcoreapplication.cpp line 589.

i have changed only method "monotonicClock32". Any idea what i need to change in code to bypass this error? Tnx

peniwize commented 6 years ago

An object that inherits (is a) QObject, which was created by the thread with ID 0x0x14f3a8, cannot receive events directly from another thread. In this case that's the thread with ID 0x0x39bd40. This is may be a design error that was silently ignored by previous versions of Qt. I will investigate this as soon as I get a chance. In the mean time, please reply with the log output so I can reproduce the condition on my system. Even a screenshot of the log window in the application will be helpful.

An additional action that will help both of us diagnose the problem is to get a stack trace when the error/warning is issued. You can do this by trapping the message in a debugger and getting a stack trace there. To do this, replace main (in Main.cpp) with the following code:


static g_pPrevQtMsgHandler = nullptr;

static void loggingHookForQt(QtMsgType iLogLevel, const QMessageLogContext &iLogContext, const QString &iMessage)
{
    // Filter messages that should *not* be logged.
    static QRegularExpression const lRegExs[] = {
        QRegularExpression("Cannot send events to objects owned by a different thread.", QRegularExpression::CaseInsensitiveOption),
    };
    for (auto const& lRegEx : lRegExs)
    {
        if (lRegEx.isValid() && lRegEx.match(iMessage).hasMatch())
        {
#if defined(Q_OS_WIN)
            DebugBreak();
#endif // #if defined(Q_OS_WIN)
        }
    }

    if (g_pPrevQtMsgHandler)
    {
        g_pPrevQtMsgHandler(iLogLevel, iLogContext, iMessage);
    }
}

int
main(int argc, char *argv[])
{
    // Install Qt logging hook for QDebug message processing.
    g_pPrevQtMsgHandler = qInstallMessageHandler(loggingHookForQt);

#ifdef GENERATE_GAT_PACKET_FOR_TESTING
    GeneratePacket_SR81();
#endif // #ifdef GENERATE_GAT_PACKET_FOR_TESTING

    QApplication application(argc, argv);
    qRegisterMetaType<GatHostStartupStateId>("GatHostStartupStateId");
    qRegisterMetaType<GatLinkLayer::StateId>("GatLinkLayer::StateId");
    qRegisterMetaType<GatHostCmd::CmdState>("GatHostCmd::CmdState");
    MainWindow mainWnd;
    mainWnd.show();
    return application.exec();
}

Regards, - Matt

IG0111 commented 6 years ago

Hello,

callstack: callstack

log: log

Regards,

peniwize commented 6 years ago

Hi Igor,

I've created a new branch named "github_issue_1" that contains "Doc/GitHub_Issue_1_Notes.txt" where I've documented my findings. I believe I know what's wrong. I do not currently have a test bench set up that will allow me to debug and test so it may be some days before I can get a fix completed. The root of the problem seems to be that "MainWindow::operationFailedDpc()" will reset "activeGatCmd", which will cause the ASSERT you're seeing when it does this after the GatHost thread has already released its reference. If this turns out to be true then it explains why the bug is intermittent.

One dirty hack you could employ for now is to comment out "activeGatCmd_ = nullptr;" in "MainWindow::operationFailed_Dpc()". I believe this will only produce a small slow memory leak. Please comment back with your findings if you try this hack.

Regards,

- Matt