summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJuha Kukkonen <ext-juha.kukkonen@nokia.com>2012-04-20 15:20:39 +0300
committerPasi Pentikäinen <ext-pasi.a.pentikainen@nokia.com>2012-04-26 10:35:48 +0200
commit838bd8e10de7945f1c25784842669271629cdeaa (patch)
tree1d4f891a191876c4674ccf403d53d03bf60b3d06
parentef13a7c86364f5e4d0385aa991c94a264e896d56 (diff)
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> (cherry picked from commit 3a4acb35029efb1d1f5a0e8d24ddd5838f8f89b9)
-rw-r--r--src/corelib/thread/qthread_symbian.cpp11
-rw-r--r--tests/auto/qthread/tst_qthread.cpp146
2 files changed, 156 insertions, 1 deletions
diff --git a/src/corelib/thread/qthread_symbian.cpp b/src/corelib/thread/qthread_symbian.cpp
index 0cddb680dd..149da9c3b8 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 4a8baa0a98..2dd71a48ee 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"