This forum has been archived. All content is frozen. Please use KDE Discuss instead.

Thread chaos with some main-windows

Tags: None
(comma "," separated)
The User
KDE Developer
Posts
647
Karma
0
OS

Thread chaos with some main-windows

Thu Jan 07, 2010 11:13 pm
Hi!

I'm currently doing some experiments with signal handlers.
After some working examples I started with something more powerful:
Code: Select all
#include <stdlib.h>
#include <signal.h>
#include <iostream>
#include <stdexcept>
#include <pthread.h>

#include <QtCore>
#include <QtGui>
#include <QtDebug>
#include <QThreadStorage>

/*Define signal catching stuff */
using namespace std;

struct seg_error : public runtime_error
{
  int key;
  seg_error(string message = "", int _key = 0) : runtime_error(message), key(_key) {}
};

class LikePlasmoid : public QLabel
{
    Q_OBJECT
public:
    LikePlasmoid(const QString& text, QWidget *parent = 0) : QLabel(text, parent)
    {
        setWindowFlags(Qt::Window);
    }
};

class ThreadCrashPlasmoid : public LikePlasmoid
{
public:
    ThreadCrashPlasmoid(uint time) : LikePlasmoid("Crash after " + QString::number(time) + " seconds (separate thread)")
    {
        class Crasher : public QThread
        {
            uint time;
        public:
            Crasher(uint time, QObject *parent = 0) : QThread(parent), time(time)
            {
            }
            void run()
            {
                usleep(time);
                int *x = 0;
                qDebug() << *x;
            }
        };
        (new Crasher(time, this))->start();
    }
};

class EventCrashPlasmoid : public LikePlasmoid
{
public:
    EventCrashPlasmoid(uint time) : LikePlasmoid("Crash after " + QString::number(time) + " seconds (event thread)")
    {
        startTimer(time);
    }
protected:
    void timerEvent(QTimerEvent*)
    {
        int *x = 0;
        qDebug() << *x;
    }
};

class CrashFreeApp : public QApplication
{
    Q_OBJECT
public:
    static struct sigaction sa;
    static QThreadStorage<bool*> useHandler;
    static void fault(int key)
    {
        if(!useHandler.hasLocalData() || *useHandler.localData())
        {
            useHandler.setLocalData(new bool(false));
            QMessageBox *box = new QMessageBox(QMessageBox::Critical, QString("Error"), QString("This dialog should be replaced by DrKonqi!"), QMessageBox::Ok);
            box->setAttribute(Qt::WA_DeleteOnClose);
            box->show();
            throw seg_error("Segmentation Fault! Error key is: ", key);
        }
        else
            SIG_DFL(key);
    }
    static void installSignalHandlers()
    {
//         sa.sa_flags = SA_SIGINFO;
        sa.sa_flags = SA_NODEFER;
        sigemptyset(&sa.sa_mask);
        sa.sa_handler = fault;

        sigset_t mask;
        sigemptyset(&mask);
       
        #ifdef SIGSEGV
        sigaction(SIGSEGV, &sa, 0);
        sigaddset(&mask, SIGSEGV);
        #endif
        #ifdef SIGFPE
        sigaction(SIGFPE, &sa, 0);
        sigaddset(&mask, SIGFPE);
        #endif
        #ifdef SIGILL
        sigaction(SIGILL, &sa, 0);
        sigaddset(&mask, SIGILL);
        #endif
       
        pthread_sigmask(SIG_UNBLOCK, &mask, 0);
    }
    CrashFreeApp(int argc, char ** argv) : QApplication(argc,argv)
    {
        //Install signal handlers
        installSignalHandlers();
        //signal(SIGABRT, segmentationFault);
    }
    bool notify ( QObject * receiver, QEvent * event )
    {
        try
        {
            return QApplication::notify(receiver, event);
        }
        catch (seg_error & e)
        { //Catch possible crashes
            try
            {
                useHandler.setLocalData(new bool(true));
                cout << e.what() << endl;
                emit crashCatched(receiver, event, e);
            }
            catch(...)
            {
                useHandler.setLocalData(new bool(false));
                throw;
            }
        }
        return false;
    }

    Q_SIGNALS:
        void crashCatched(QObject*, QEvent*, seg_error&);
};

struct sigaction CrashFreeApp::sa;
QThreadStorage<bool*> CrashFreeApp::useHandler;

class LikeCorona : public QObject
{
    Q_OBJECT
public:
    LikeCorona() : QObject()
    {
        connect(qApp, SIGNAL(crashCatched(QObject*, QEvent*, seg_error&)), this, SLOT(processCrash(QObject *, QEvent *, seg_error&)), Qt::DirectConnection);
        LikePlasmoid *applet = new ThreadCrashPlasmoid(5);
        applet->resize(250, 150);
        applet->show();
        applet = new EventCrashPlasmoid(7);
        applet->resize(250, 150);
        applet->show();
        applet = new ThreadCrashPlasmoid(10);
        applet->resize(250, 150);
        applet->show();
        applet = new EventCrashPlasmoid(13);
        applet->resize(250, 150);
        applet->show();
    }

public slots:
    void processCrash(QObject * obj, QEvent * evt, seg_error& err) {
        //Handle the crash on the app itself
        qDebug() << "It crashed on" << obj << evt;
        if(LikePlasmoid *applet = qobject_cast<LikePlasmoid*>(obj))
        {
            qDebug() << "The receiver is a Plasmoid!";
            applet->deleteLater();
        }
        else
        {
            QObject *obj2 = QThread::currentThread()->parent();
            while(obj2 != 0)
            {
                if(LikePlasmoid *applet = qobject_cast<LikePlasmoid*>(obj2))
                {
                    qDebug() << "The thread is owned by a Plasmoid!";
                    applet->deleteLater();
                    return;
                }
            }
            qDebug() << "There were no Plasmoids, let's crash!!!!";
            throw err;
        }
    }

private:
};

int main(int argc, char ** argv)
{
        CrashFreeApp app(argc, argv);

        LikeCorona *likeCorona = new LikeCorona;

        return app.exec();
}

#include "likeplasmoid.moc"

The signal-handling is no problem (it worked nearly the same way with a simplier example) but I get strange runtime error, they are not reproducable, but it's always something with "QPixmap outside of GUI-Thread", "Cannot create children for parent that is in a different thread. (Parent is Oxygen...)", the application crashes with "X Error: BadPixmap" or "Fatal IO error". These faults happen before my experiments with null-pointers. (they should happen after at least 5 seconds) Any idea where I could break the GUI-thread?

Compilation:
Code: Select all
moc likeplasmoid.cpp > likeplasmoid.moc
g++ -o likeplasmoid likeplasmoid.cpp -funwind-tables -fnon-call-exceptions -fasynchronous-unwind-tables -I/usr/include/QtCore -I/usr/include/QtGui -lQtCore -lQtGui
./likeplasmoid


Thank you!

The User
User avatar
bcooksley
Administrator
Posts
19765
Karma
87
OS
Qt does not use Exceptions, which may lead to internal corruption, leading to failure of the GUI thread.


KDE Sysadmin
[img]content/bcooksley_sig.png[/img]
The User
KDE Developer
Posts
647
Karma
0
OS
The runtime error occur before I throw any exceptions.

Edit:
Sorry, I forgot that setTimer takes the number of milliseconds.
Forget about this thread. ;)

PPS:
It had nothing todo with exceptions: It was the QMessageBox...


Bookmarks



Who is online

Registered users: abc72656, Bing [Bot], daret, Google [Bot], Sogou [Bot], Yahoo [Bot]