Qt4: fix Genode thread deletion

With this patch the Genode thread used by the QThread class gets deleted
when 'QThread::wait()' gets called and the timeout didn't trigger or when
'QThread::terminate()' gets called.

Fixes #193.
This commit is contained in:
Christian Prochaska 2012-05-03 20:10:02 +02:00 committed by Norman Feske
parent c3fcd834b0
commit b448a67151
3 changed files with 58 additions and 23 deletions

View File

@ -870,7 +870,7 @@ diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h
#include "qplatformdefs.h"
#include "QtCore/qthread.h"
#include "QtCore/qmutex.h"
@@ -136,6 +140,39 @@
@@ -136,6 +140,56 @@
static QThread *threadForId(int id);
#ifdef Q_OS_UNIX
@ -878,17 +878,34 @@ diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h
+
+ class Genode_thread : public Genode::Thread_qt
+ {
+ public:
+ Genode_thread(QThread *qthread) : _qthread(qthread) { }
+ private:
+
+ virtual void entry()
+ {
+ QThreadPrivate::start(_qthread);
+ QThreadPrivate::finish(_qthread);
+ }
+ /*
+ * The '_finished_lock' is necessary because 'QThreadPrivate::mutex'
+ * uses a 'Genode::Timed_semaphore' internally and it isn't safe
+ * to delete a Genode thread that just called 'Semaphore::up()',
+ * because the 'Semaphore::_meta_lock' could still be locked.
+ */
+ Genode::Lock _finished_lock;
+ QThread *_qthread;
+
+ private:
+ QThread *_qthread;
+ public:
+
+ Genode_thread(QThread *qthread)
+ : _finished_lock(Genode::Lock::LOCKED),
+ _qthread(qthread) { }
+
+ virtual void entry()
+ {
+ QThreadPrivate::start(_qthread);
+ QThreadPrivate::finish(_qthread);
+ _finished_lock.unlock();
+ }
+
+ void join()
+ {
+ _finished_lock.lock();
+ }
+ };
+
+ Genode_thread *genode_thread;
@ -910,7 +927,7 @@ diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h
pthread_t thread_id;
QWaitCondition thread_done;
@@ -145,6 +182,7 @@
@@ -145,6 +199,7 @@
#else
static void finish(void *);
#endif

View File

@ -188,8 +188,8 @@ void QThreadPrivate::finish(QThread *thr)
void *data = &d->data->tls;
QThreadStorageData::finish((void **)data);
QThreadPrivate::tls.remove(QThread::currentThreadId());
QThreadPrivate::tls.remove(QThread::currentThreadId());
d->thread_id = 0;
d->thread_done.wakeAll();
}
@ -336,15 +336,29 @@ void QThread::terminate()
Q_D(QThread);
QMutexLocker locker(&d->mutex);
if (QThreadPrivate::tls.value(QThread::currentThreadId()).termination_enabled) {
delete d->genode_thread;
d->genode_thread = 0;
d->terminated = true;
d->running = false;
}
if (QThreadPrivate::tls.value(QThread::currentThreadId()).termination_enabled) {
if (d->genode_thread) {
delete d->genode_thread;
d->genode_thread = 0;
}
d->terminated = true;
d->running = false;
}
}
static inline void join_and_delete_genode_thread(QThreadPrivate *d)
{
if (d->genode_thread) {
d->genode_thread->join();
delete d->genode_thread;
d->genode_thread = 0;
}
}
/*!
Blocks the thread until either of these conditions is met:
@ -374,14 +388,18 @@ bool QThread::wait(unsigned long time)
return false;
}
if (d->finished || !d->running)
if (d->finished || !d->running) {
join_and_delete_genode_thread(d);
return true;
}
while (d->running) {
if (!d->thread_done.wait(locker.mutex(), time))
return false;
}
join_and_delete_genode_thread(d);
return true;
}

View File

@ -251,10 +251,10 @@ bool QWaitCondition::wait(QMutex *mutex, unsigned long time)
} else {
try {
d->sem.down((Genode::Alarm::Time) time);
result = true;
} catch (Genode::Timeout_exception) {
return false;
result = false;
}
return true;
}
mutex->lock();