diff options
author | David Faure <david.faure@kdab.com> | 2013-03-15 19:48:59 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-03-23 02:06:47 +0100 |
commit | d4adee7851790dd6949424de083756f49af891db (patch) | |
tree | 00416d4afc19fd37ce6f3a121d842ee0914ad5e7 /src/corelib/thread/qthread_unix.cpp | |
parent | c550a5d42c1188c0ccd11c205665e2608dbec61f (diff) |
Fix race condition in QThread::setPriority
The value of priority was read without the mutex locked, from within
the thread.
Had to extract a QThreadPrivate::setPriority method so that it can be called
with the mutex already locked. So if the main thread calls setPriority
while the thread is starting, it will be either be before or after the
"re-set priority" code at thread startup, but at least not in the middle of it.
Change-Id: I7a054f68623f61482c749274da66f3b2dcd8bcee
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
Diffstat (limited to 'src/corelib/thread/qthread_unix.cpp')
-rw-r--r-- | src/corelib/thread/qthread_unix.cpp | 39 |
1 files changed, 17 insertions, 22 deletions
diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index b7e94366fe..f123e1813b 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -300,17 +300,18 @@ void *QThreadPrivate::start(void *arg) QThread *thr = reinterpret_cast<QThread *>(arg); QThreadData *data = QThreadData::get2(thr); - // do we need to reset the thread priority? - if (int(thr->d_func()->priority) & ThreadPriorityResetFlag) { - thr->setPriority(QThread::Priority(thr->d_func()->priority & ~ThreadPriorityResetFlag)); - } - - data->threadId = (Qt::HANDLE)pthread_self(); - set_thread_data(data); - - data->ref(); { QMutexLocker locker(&thr->d_func()->mutex); + + // do we need to reset the thread priority? + if (int(thr->d_func()->priority) & ThreadPriorityResetFlag) { + thr->d_func()->setPriority(QThread::Priority(thr->d_func()->priority & ~ThreadPriorityResetFlag)); + } + + data->threadId = (Qt::HANDLE)pthread_self(); + set_thread_data(data); + + data->ref(); data->quitNow = thr->d_func()->exited; } @@ -687,16 +688,10 @@ void QThread::setTerminationEnabled(bool enabled) #endif } -void QThread::setPriority(Priority priority) +// Caller must lock the mutex +void QThreadPrivate::setPriority(QThread::Priority threadPriority) { - Q_D(QThread); - QMutexLocker locker(&d->mutex); - if (!d->running) { - qWarning("QThread::setPriority: Cannot set priority, thread is not running"); - return; - } - - d->priority = priority; + priority = threadPriority; // copied from start() with a few modifications: @@ -704,7 +699,7 @@ void QThread::setPriority(Priority priority) int sched_policy; sched_param param; - if (pthread_getschedparam(d->thread_id, &sched_policy, ¶m) != 0) { + if (pthread_getschedparam(thread_id, &sched_policy, ¶m) != 0) { // failed to get the scheduling policy, don't bother setting // the priority qWarning("QThread::setPriority: Cannot get scheduler parameters"); @@ -720,15 +715,15 @@ void QThread::setPriority(Priority priority) } param.sched_priority = prio; - int status = pthread_setschedparam(d->thread_id, sched_policy, ¶m); + int status = pthread_setschedparam(thread_id, sched_policy, ¶m); # ifdef SCHED_IDLE // were we trying to set to idle priority and failed? if (status == -1 && sched_policy == SCHED_IDLE && errno == EINVAL) { // reset to lowest priority possible - pthread_getschedparam(d->thread_id, &sched_policy, ¶m); + pthread_getschedparam(thread_id, &sched_policy, ¶m); param.sched_priority = sched_get_priority_min(sched_policy); - pthread_setschedparam(d->thread_id, sched_policy, ¶m); + pthread_setschedparam(thread_id, sched_policy, ¶m); } # else Q_UNUSED(status); |