Avoid corruption in Q(Open)GLFunctions when used on multiple threads

Using Q(Open)GLFunctions concurrently on multiple threads had some issues
due to incorrect synchronization: The m_groups list in the
QOpenGLMultiGroupSharedResource, in which the Q(Open)GLFunctions instance
is stored, became corrupted under certain scenarios, for example in the
tst_qglthreads autotest and any two threads that happen to enter an
initializeOpenGLFunctions() or QOpenGLContext::functions() call concurrently.

Locking in value() has been introduced in 666c25c089acf7fcc9e9a6b7665074c6286d604e
to fix such issues, however using the context group's mutex is not enough: that still
allows two threads using two contexts with a different context group to concurrently
enter insert(). Instead, the MultiGroupSharedResource has to have its own mutex
to protect its own member variables.

Task-number: QTBUG-38771
Change-Id: If01c44c2084b95e487bc9146576ca180ed8044da
Reviewed-by: Jørgen Lind <jorgen.lind@digia.com>
This commit is contained in:
Laszlo Agocs 2014-05-05 17:52:47 +02:00 committed by The Qt Project
parent f85ab84414
commit 295786d946
2 changed files with 6 additions and 2 deletions

View File

@ -1345,7 +1345,8 @@ void QOpenGLSharedResourceGuard::freeResource(QOpenGLContext *context)
QOpenGLMultiGroupSharedResource instance.
*/
QOpenGLMultiGroupSharedResource::QOpenGLMultiGroupSharedResource()
: active(0)
: active(0),
m_mutex(QMutex::Recursive)
{
#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG
qDebug("Creating context group resource object %p.", this);

View File

@ -171,7 +171,9 @@ public:
template <typename T>
T *value(QOpenGLContext *context) {
QOpenGLContextGroup *group = context->shareGroup();
QMutexLocker locker(&group->d_func()->m_mutex);
// Have to use our own mutex here, not the group's, since
// m_groups has to be protected too against any concurrent access.
QMutexLocker locker(&m_mutex);
T *resource = static_cast<T *>(group->d_func()->m_resources.value(this, 0));
if (!resource) {
resource = new T(context);
@ -183,6 +185,7 @@ public:
private:
QAtomicInt active;
QList<QOpenGLContextGroup *> m_groups;
QMutex m_mutex;
};
class QPaintEngineEx;