From 570e7b38487455d394b5b74a59edc639f3dc416f Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Thu, 13 Jan 2011 15:52:17 +0200 Subject: Fix QSystemSemaphore handle management issues in Symbian QSystemSemaphore native RSemaphore handle was unnecessarily created again on each acquire. The creation logic was also susceptible for random failures when two or more threads tried simultaneously acquire the semaphore. Task-number: QTBUG-16615 Reviewed-by: Janne Koskinen --- src/corelib/kernel/qsystemsemaphore_symbian.cpp | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/corelib/kernel/qsystemsemaphore_symbian.cpp b/src/corelib/kernel/qsystemsemaphore_symbian.cpp index a25a119..07cfffc 100644 --- a/src/corelib/kernel/qsystemsemaphore_symbian.cpp +++ b/src/corelib/kernel/qsystemsemaphore_symbian.cpp @@ -73,6 +73,9 @@ void QSystemSemaphorePrivate::setErrorString(const QString &function, int err) case KErrInUse: errorString = QCoreApplication::tr("%1: out of resources", "QSystemSemaphore").arg(function); error = QSystemSemaphore::OutOfResources; + case KErrPermissionDenied: + errorString = QCoreApplication::tr("%1: permission denied", "QSystemSemaphore").arg(function); + error = QSystemSemaphore::PermissionDenied; break; default: errorString = QCoreApplication::tr("%1: unknown error %2", "QSystemSemaphore").arg(function).arg(err); @@ -86,15 +89,24 @@ default: int QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode) { + if (semaphore.Handle()) { + return semaphore.Handle(); + } + // don't allow making handles on empty keys if (key.isEmpty()) return 0; + QString safeName = makeKeyFileName(); TPtrC name(qt_QString2TPtrC(safeName)); - int err; - err = semaphore.OpenGlobal(name,EOwnerProcess); - if (err == KErrNotFound){ - err = semaphore.CreateGlobal(name,initialValue, EOwnerProcess); + int err = KErrAlreadyExists; + int tryCount = 10; + // Sort out race conditions by retrying several times until existing handle is acquired. + // Sometimes opening can fail inexplicably with KErrPermissionDenied many times in a row. + while (err != KErrNoMemory && err != KErrNone && tryCount-- >= 0) { + err = semaphore.CreateGlobal(name, initialValue, EOwnerProcess); + if (err != KErrNoMemory && err != KErrNone) + err = semaphore.OpenGlobal(name,EOwnerProcess); } if (err){ setErrorString(QLatin1String("QSystemSemaphore::handle"),err); -- cgit v0.12