From 3a4acb35029efb1d1f5a0e8d24ddd5838f8f89b9 Mon Sep 17 00:00:00 2001 From: Juha Kukkonen Date: Fri, 20 Apr 2012 15:20:39 +0300 Subject: Fix QThread start failure due to bad thread name on Symbian MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Pasi Pentikäinen --- src/corelib/thread/qthread_symbian.cpp | 11 ++- tests/auto/qthread/tst_qthread.cpp | 146 +++++++++++++++++++++++++++++++++ 2 files changed, 156 insertions(+), 1 deletion(-) 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 #include +#include // This can be manually enabled if debugging thread problems #ifdef QT_USE_RTTI_IN_THREAD_CLASSNAME #include @@ -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 name; threadNameBasePtr.Set(threadNameBasePtr.Left(qMin(threadNameBasePtr.Length(), name.MaxLength() - 8))); const int MaxRetries = 10; for (int i=0; i + +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" -- cgit v0.12