Segfault during first window constructors on OS X Lion.



  • I have a Qt application running in Linux and am trying to get running on OS X again. I previously had it running on 10.6 with Qt 4.7.0, but am now trying with Qt 4.8 and on OS X 10.7. The program works perfectly on linux, but am having a consistent problem when trying to construct the first QWidget.

    The way the program is designed is a QApplication is created, another thread ( posix, not Qt ) is created and run, and then the main thread goes into the qApp::exec() loop. The second thread then gets messages and starts various components of the program, one of the eventually will be to open a QGLWidget. This widget is started by passing a custom event to the Qt thread. Any ideas or help will be greatly appreciated...

    During this stage on OS X I get a segfault and get the following stderr:

    @QObject::setParent: Cannot set parent, new parent is in a different thread
    QPixmap: It is not safe to use pixmaps outside the GUI thread
    QPixmap: It is not safe to use pixmaps outside the GUI thread
    Segmentation fault: 11 (core dumped)
    @

    The backtrace from apples report is as follows:

    @Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
    0 QtGui 0x000000010d049e78 QPixmap::isQBitmap() const + 8
    1 QtGui 0x000000010d0a67ff QBrush::isOpaque() const + 447
    2 QtGui 0x000000010d000e56 QWidgetPrivate::init(QWidget*, QFlagsQt::WindowType) + 718
    3 QtGui 0x000000010d001042 QWidget::QWidget(QWidgetPrivate&, QWidget*, QFlagsQt::WindowType) + 86
    4 QtOpenGL 0x000000010db4ede9 QGLWidget::QGLWidget(QGLFormat const&, QWidget*, QGLWidget const*, QFlagsQt::WindowType) + 79
    5 MediaEngine 0x000000010bac3d88 BaseWindow::BaseWindow() + 172
    6 MediaEngine 0x000000010bacf756 VideoWindow::VideoWindow() + 24
    7 MediaEngine 0x000000010baac90b GuiManager2::CreateGlWindow(WindowConfig) + 401
    8 MediaEngine 0x000000010bab01c2 GuiManager2::customEvent(QEvent*) + 528
    9 QtCore 0x000000010ccae29d QObject::event(QEvent*) + 1191
    10 QtGui 0x000000010cfaf308 QApplicationPrivate::notify_helper(QObject*, QEvent*) + 304
    11 QtGui 0x000000010cfaf589 QApplication::notify(QObject*, QEvent*) + 603
    12 QtCore 0x000000010cc9a156 QCoreApplication::notifyInternal(QObject*, QEvent*) + 104
    13 QtCore 0x000000010cc9a543 QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) + 557
    14 com.apple.CoreFoundation 0x00007fff88c356e1 CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION + 17
    15 com.apple.CoreFoundation 0x00007fff88c34f4d __CFRunLoopDoSources0 + 253
    16 com.apple.CoreFoundation 0x00007fff88c5bd39 __CFRunLoopRun + 905
    17 com.apple.CoreFoundation 0x00007fff88c5b676 CFRunLoopRunSpecific + 230
    18 com.apple.HIToolbox 0x00007fff8cb1b31f RunCurrentEventLoopInMode + 277
    19 com.apple.HIToolbox 0x00007fff8cb225c9 ReceiveNextEventCommon + 355
    20 com.apple.HIToolbox 0x00007fff8cb22456 BlockUntilNextEventMatchingListInMode + 62
    21 com.apple.AppKit 0x00007fff86e04f5d _DPSNextEvent + 659
    22 com.apple.AppKit 0x00007fff86e04861 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 135
    23 com.apple.AppKit 0x00007fff86e0119d -[NSApplication run] + 470
    24 QtGui 0x000000010cf6b090 QEventDispatcherMac::processEvents(QFlagsQEventLoop::ProcessEventsFlag) + 840
    25 QtCore 0x000000010cc97718 QEventLoop::exec(QFlagsQEventLoop::ProcessEventsFlag) + 394
    26 QtCore 0x000000010cc9a88b QCoreApplication::exec() + 175
    27 MediaEngine 0x000000010bc65c68 MagorQtApp::MainRun() + 616
    28 MediaEngine 0x000000010b972009 MediaAdmin::Run(int&, char**) + 143 (MediaAdmin.cpp:82)
    29 MediaEngine 0x000000010b9a9056 main + 294 (main.cpp:46)
    30 MediaEngine 0x000000010b9667a4 start + 52
    @



  • Hard to judge without any code.

    But the error message is quite clear: You try to set a parent in one thread to a QObject created in another thread. That doesn't work.



  • Ya, that's what confuses me too. The object is a QGLWidget, it is constructed on the main thread ( as you can see in the backtrace ), and there is no parent. The only QObject created on a different thread than the main is the QEvent subclass to pass event to the GuiManager2.

    GuiManager2 is a QObject created on the stack on the main thread before QApp->exec(). Posting event from 2nd thread to main thread:

    @QApplication::postEvent((QObject*)this, new CustomQtStartEvent(winConfig));
    @

    Handling this customEvent is where we construct the new window:

    @void GuiManager2::customEvent(QEvent *event)
    {
    if(event->type() == (QEvent::Type)CUSTOM_NEW_WINDOW)
    {
    mpTempGlWindow = new VideoWindow();
    int result = mpTempGlWindow->Initialize(config);
    ...
    }
    }
    @

    Constructor for the QGLWidget:

    @
    BaseWindow::BaseWindow():
    QGLWidget(QGLFormat(QGL::DoubleBuffer)),
    @

    From the constructor, the *parent is passed as 0 so we shouldn't even have a parent for this window. Inside the QGLWidget itself all it's classes should be properly parented to it correct?



  • Still hard to say what's going on here. The only thing that's clear is that a second thread entered the game at the wrong point. I would always trust Qt here instead of a programmer's assertion.

    Best thing would be to boil down your app to a small test case that does nothing more than reproduce the error. Chances are good that you find the mistake on the way.



  • Hi guys!
    I'm having exactly the same problem.

    I'm running OSX Mountain Lion and Qt 4.8.3, and I have had to compile Qt SQL plugin myself. The code is so simple:
    @#include "QMainWindowEPGEditor.h"

    #include "QSqlDatabase.h"
    #include "QMessageBox.h"
    #include "QSqlError.h"
    #include "QSqlQuery.h"
    #include "QDebug.h"

    QMainWindowEPGEditor::QMainWindowEPGEditor(): QMainWindow()
    {
    ui.setupUi(this);
    this->initialize();
    }

    QMainWindowEPGEditor::~QMainWindowEPGEditor()
    {
    }

    void QMainWindowEPGEditor::initialize()
    {
    this->openDatabase();
    this->queryData();
    this->closeDatabase();
    }

    void QMainWindowEPGEditor::openDatabase()
    {
    mDatabase = QSqlDatabase::addDatabase("QMYSQL");
    mDatabase.setHostName("XXXXX");
    mDatabase.setPort(XXXX);
    mDatabase.setDatabaseName("XXXX");
    mDatabase.setUserName("XXXXXX");
    mDatabase.setPassword("XXXXXXX");
    if (!mDatabase.open())
    {
    QMessageBox::critical(0, QObject::tr("Database Error"), mDatabase.lastError().text());
    }
    }

    void QMainWindowEPGEditor::queryData()
    {
    QSqlQuery query;
    query.exec("SELECT * FROM XXXX");
    while (query.next())
    {
    QString channelName = query.value(1).toString();
    ui.listWidgetChannels->addItem(channelName);
    }
    }

    void QMainWindowEPGEditor::closeDatabase()
    {
    mDatabase.close();
    }
    @

    So, when I remove the code related with database there is no warning messages, and no crash. But if I put just the line
    @
    mDatabase = QSqlDatabase::addDatabase("QMYSQL");
    @
    without the rest of the code, the application crashes when I call show() method on the QMainWindowEPGEditor, and the warning messages are shown.

    As you can see, I'm not using multithreading myself. Maybe libqsqlmysql is using...

    I have spent a lot of hours trying to figure this out,
    Ideas?

    Thanks in advance,
    Robert.



  • I have found something out.
    If I switch from
    @
    mDatabase = QSqlDatabase::addDatabase("QMYSQL");
    @
    to
    @
    mDatabase = QSqlDatabase::addDatabase("QSQLITE");
    @
    There is no crash or warning messages. So there has to be something with mysql plugin. Right?


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.