diff options
author | Juha Kukkonen <ext-juha.kukkonen@nokia.com> | 2012-04-20 12:20:39 (GMT) |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-04-25 23:30:12 (GMT) |
commit | 3a4acb35029efb1d1f5a0e8d24ddd5838f8f89b9 (patch) | |
tree | 43c1cb181df3075e29113f3ab3c3a1f40456666b | |
parent | a2dfb824021ea01c1c9c81461b9f275643793542 (diff) | |
download | Qt-3a4acb35029efb1d1f5a0e8d24ddd5838f8f89b9.zip Qt-3a4acb35029efb1d1f5a0e8d24ddd5838f8f89b9.tar.gz Qt-3a4acb35029efb1d1f5a0e8d24ddd5838f8f89b9.tar.bz2 |
Fix QThread start failure due to bad thread name on Symbian
RThread::Create() deems a thread name to be invalid, if it contains
any of the characters: "*", "?", ":" or character is outside
0x20 - 0x7e range. This matches to the logic in User::ValidateName()
that is used by RThread::Create() to validate thread name.
In addition, maximum thread name length is 80 character on Symbian.
It was possible that thread name contained e.g. colon that caused
RThread::Create() to fail with KErrBadName (-28).
Fix ensures that thread name contains only allowed characters.
Task-number: ou1cimx1#996187
Change-Id: Ie6dd8c60bfed4e2f6cc48607ff0ff940d9cdae8a
Reviewed-by: Murray Read <ext-murray.2.read@nokia.com>
Reviewed-by: Pasi Pentikäinen <ext-pasi.a.pentikainen@nokia.com>
-rw-r--r-- | src/corelib/thread/qthread_symbian.cpp | 11 | ||||
-rw-r--r-- | tests/auto/qthread/tst_qthread.cpp | 146 |
2 files changed, 156 insertions, 1 deletions
diff --git a/src/corelib/thread/qthread_symbian.cpp b/src/corelib/thread/qthread_symbian.cpp index 0cddb68..149da9c 100644 --- a/src/corelib/thread/qthread_symbian.cpp +++ b/src/corelib/thread/qthread_symbian.cpp @@ -53,6 +53,7 @@ #include <hal_data.h> #include <e32math.h> +#include <QRegExp> // This can be manually enabled if debugging thread problems #ifdef QT_USE_RTTI_IN_THREAD_CLASSNAME #include <typeinfo> @@ -533,8 +534,16 @@ void QThread::start(Priority priority) className = QLatin1String(rttiName); #endif QString threadNameBase = QString(QLatin1String("%1_%2_v=0x%3_")).arg(objectName()).arg(className).arg(*(uint*)this,8,16,QLatin1Char('0')); + // Thread name can contain only characters allowed by User::ValidateName() otherwise RThread::Create fails. + // Not allowed characters are: + // - any character outside range 0x20 - 0x7e + // - or asterisk, question mark or colon + const QRegExp notAllowedChars(QLatin1String("[^\\x20-\\x7e]|\\*|\\?|\\:")); + threadNameBase.replace(notAllowedChars, QLatin1String("_")); + TPtrC threadNameBasePtr(qt_QString2TPtrC(threadNameBase)); - TName name; + // max thread name length is KMaxKernelName + TBuf<KMaxKernelName> name; threadNameBasePtr.Set(threadNameBasePtr.Left(qMin(threadNameBasePtr.Length(), name.MaxLength() - 8))); const int MaxRetries = 10; for (int i=0; i<MaxRetries && code == KErrAlreadyExists; i++) { diff --git a/tests/auto/qthread/tst_qthread.cpp b/tests/auto/qthread/tst_qthread.cpp index 4a8baa0..2dd71a4 100644 --- a/tests/auto/qthread/tst_qthread.cpp +++ b/tests/auto/qthread/tst_qthread.cpp @@ -119,6 +119,9 @@ private slots: void startAndQuitCustomEventLoop(); void stressTest(); +#ifdef Q_OS_SYMBIAN + void threadNameTest(); +#endif }; enum { one_minute = 60 * 1000, five_minutes = 5 * one_minute }; @@ -1271,6 +1274,149 @@ void tst_QThread::startAndQuitCustomEventLoop() } } +#ifdef Q_OS_SYMBIAN +#include <QRegExp> + +namespace testNamespace { +class TestThread : public QThread +{ + Q_OBJECT +public: + TestThread(); + void run(); +public: + bool runCalled; + QString threadName; +}; + +TestThread::TestThread() : runCalled(false) +{ +} + +void TestThread::run() +{ + runCalled = true; + RThread t; + TName name = t.Name(); + threadName = QString((QChar*)name.Ptr(), name.Length()); +} +} + +void tst_QThread::threadNameTest() +{ +// On Symbian thread name consist of objectName, className and variable part. +// RThread::Create sets limitations on what are allowed characters in thread name. +// Allowed characters include chars in 0x20 - 0x7e range but not '*','?',':' +// If thread thread name contains not allowed characters RThread::Create fails. +// In addition, max thread name length is 80 chars on Symbian. + + // Reqular expression used in QThread::start for removing not allowed characters + const QRegExp notAllowedChars(QLatin1String("[^\\x20-\\x7e]|\\*|\\?|\\:")); + + // objectName contains all allowed characters + { + testNamespace::TestThread thread; + QString name; + for (int i = 0x20; i < 0x7f; i++) { + if (i != '*' && i != '?' && i != ':') { + name.append(QLatin1Char(i)); + } + } + + thread.setObjectName(name); + thread.start(); + thread.wait(); + QCOMPARE(thread.runCalled, true); + + QString expectedResult = name; + QString result = name.replace(notAllowedChars, QLatin1String("_")); + QCOMPARE(result, expectedResult); + // objectName part can be max 72 chars in thread name + QCOMPARE(thread.threadName.left(72), expectedResult.left(72)); + } + + // objectName contains all characters from range including characters deemed + // not valid by RThread::Create (*?:) + { + testNamespace::TestThread thread; + QString name; + for (int i = 0x20; i < 0x7f; i++) { + name.append(QLatin1Char(i)); + } + + thread.setObjectName(name); + thread.start(); + thread.wait(); + QCOMPARE(thread.runCalled, true); + + QString expectedResult = name; + expectedResult = expectedResult.replace(QLatin1Char('*'), QLatin1Char('_')); + expectedResult = expectedResult.replace(QLatin1Char('?'), QLatin1Char('_')); + expectedResult = expectedResult.replace(QLatin1Char(':'), QLatin1Char('_')); + QString result = name.replace(notAllowedChars, QLatin1String("_")); + QCOMPARE(result, expectedResult); + + // objectName part can be max 72 chars in thread name + QCOMPARE(thread.threadName.left(72), expectedResult.left(72)); + } + + // objectName contains only invalid characters + { + testNamespace::TestThread thread; + QString name; + for (int i = 0; i < 0x20; i++) { + name.append(QLatin1Char(i)); + } + for (int i = 0x7f; i < 0xff; i++) { + name.append(QLatin1Char(i)); + } + + thread.setObjectName(name); + thread.start(); + thread.wait(); + QCOMPARE(thread.runCalled, true); + + QString expectedResult; + expectedResult.fill(QLatin1Char('_'), name.size()); + QString result = name.replace(notAllowedChars, QLatin1String("_")); + QCOMPARE(result, expectedResult); + + // objectName part can be max 72 chars in thread name + QCOMPARE(thread.threadName.left(72), expectedResult.left(72)); + } + + // objectName longer than max thread name length (80 chars) + { + testNamespace::TestThread thread; + QString name; + for (int i = 0; i < 0xff; i++) { + name.append(QLatin1Char(i)); + } + + thread.setObjectName(name); + thread.start(); + thread.wait(); + QCOMPARE(thread.runCalled, true); + } + + // className contains not allowed characters (':') + { + testNamespace::TestThread thread; + thread.start(); + thread.wait(); + QCOMPARE(thread.runCalled, true); + QString className(QLatin1String(thread.metaObject()->className())); + QCOMPARE(className, QLatin1String("testNamespace::TestThread")); + + QString expectedResult = className; + expectedResult = className.replace(QLatin1Char(':'), QLatin1Char('_')); + QString result = className.replace(notAllowedChars, QLatin1String("_")); + QCOMPARE(result, expectedResult); + + QVERIFY(thread.threadName.contains(expectedResult)); + } +} +#endif // Q_OS_SYMBIAN QTEST_MAIN(tst_QThread) #include "tst_qthread.moc" |