Skip to content

Commit 838bd8e

Browse files
Juha KukkonenPasi Pentikäinen
Juha Kukkonen
authored and
Pasi Pentikäinen
committed
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 <[email protected]> Reviewed-by: Pasi Pentikäinen <[email protected]> (cherry picked from commit 3a4acb3)
1 parent ef13a7c commit 838bd8e

File tree

2 files changed

+156
-1
lines changed

2 files changed

+156
-1
lines changed

src/corelib/thread/qthread_symbian.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
#include <hal_data.h>
5454
#include <e32math.h>
5555

56+
#include <QRegExp>
5657
// This can be manually enabled if debugging thread problems
5758
#ifdef QT_USE_RTTI_IN_THREAD_CLASSNAME
5859
#include <typeinfo>
@@ -533,8 +534,16 @@ void QThread::start(Priority priority)
533534
className = QLatin1String(rttiName);
534535
#endif
535536
QString threadNameBase = QString(QLatin1String("%1_%2_v=0x%3_")).arg(objectName()).arg(className).arg(*(uint*)this,8,16,QLatin1Char('0'));
537+
// Thread name can contain only characters allowed by User::ValidateName() otherwise RThread::Create fails.
538+
// Not allowed characters are:
539+
// - any character outside range 0x20 - 0x7e
540+
// - or asterisk, question mark or colon
541+
const QRegExp notAllowedChars(QLatin1String("[^\\x20-\\x7e]|\\*|\\?|\\:"));
542+
threadNameBase.replace(notAllowedChars, QLatin1String("_"));
543+
536544
TPtrC threadNameBasePtr(qt_QString2TPtrC(threadNameBase));
537-
TName name;
545+
// max thread name length is KMaxKernelName
546+
TBuf<KMaxKernelName> name;
538547
threadNameBasePtr.Set(threadNameBasePtr.Left(qMin(threadNameBasePtr.Length(), name.MaxLength() - 8)));
539548
const int MaxRetries = 10;
540549
for (int i=0; i<MaxRetries && code == KErrAlreadyExists; i++) {

tests/auto/qthread/tst_qthread.cpp

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,9 @@ private slots:
119119
void startAndQuitCustomEventLoop();
120120

121121
void stressTest();
122+
#ifdef Q_OS_SYMBIAN
123+
void threadNameTest();
124+
#endif
122125
};
123126

124127
enum { one_minute = 60 * 1000, five_minutes = 5 * one_minute };
@@ -1271,6 +1274,149 @@ void tst_QThread::startAndQuitCustomEventLoop()
12711274
}
12721275
}
12731276

1277+
#ifdef Q_OS_SYMBIAN
1278+
#include <QRegExp>
1279+
1280+
namespace testNamespace {
1281+
class TestThread : public QThread
1282+
{
1283+
Q_OBJECT
1284+
public:
1285+
TestThread();
1286+
void run();
1287+
public:
1288+
bool runCalled;
1289+
QString threadName;
1290+
};
1291+
1292+
TestThread::TestThread() : runCalled(false)
1293+
{
1294+
}
1295+
1296+
void TestThread::run()
1297+
{
1298+
runCalled = true;
1299+
RThread t;
1300+
TName name = t.Name();
1301+
threadName = QString((QChar*)name.Ptr(), name.Length());
1302+
}
1303+
}
1304+
1305+
void tst_QThread::threadNameTest()
1306+
{
1307+
// On Symbian thread name consist of objectName, className and variable part.
1308+
// RThread::Create sets limitations on what are allowed characters in thread name.
1309+
// Allowed characters include chars in 0x20 - 0x7e range but not '*','?',':'
1310+
// If thread thread name contains not allowed characters RThread::Create fails.
1311+
// In addition, max thread name length is 80 chars on Symbian.
1312+
1313+
// Reqular expression used in QThread::start for removing not allowed characters
1314+
const QRegExp notAllowedChars(QLatin1String("[^\\x20-\\x7e]|\\*|\\?|\\:"));
1315+
1316+
// objectName contains all allowed characters
1317+
{
1318+
testNamespace::TestThread thread;
1319+
QString name;
1320+
for (int i = 0x20; i < 0x7f; i++) {
1321+
if (i != '*' && i != '?' && i != ':') {
1322+
name.append(QLatin1Char(i));
1323+
}
1324+
}
1325+
1326+
thread.setObjectName(name);
1327+
thread.start();
1328+
thread.wait();
1329+
QCOMPARE(thread.runCalled, true);
1330+
1331+
QString expectedResult = name;
1332+
QString result = name.replace(notAllowedChars, QLatin1String("_"));
1333+
QCOMPARE(result, expectedResult);
1334+
// objectName part can be max 72 chars in thread name
1335+
QCOMPARE(thread.threadName.left(72), expectedResult.left(72));
1336+
}
1337+
1338+
// objectName contains all characters from range including characters deemed
1339+
// not valid by RThread::Create (*?:)
1340+
{
1341+
testNamespace::TestThread thread;
1342+
QString name;
1343+
for (int i = 0x20; i < 0x7f; i++) {
1344+
name.append(QLatin1Char(i));
1345+
}
1346+
1347+
thread.setObjectName(name);
1348+
thread.start();
1349+
thread.wait();
1350+
QCOMPARE(thread.runCalled, true);
1351+
1352+
QString expectedResult = name;
1353+
expectedResult = expectedResult.replace(QLatin1Char('*'), QLatin1Char('_'));
1354+
expectedResult = expectedResult.replace(QLatin1Char('?'), QLatin1Char('_'));
1355+
expectedResult = expectedResult.replace(QLatin1Char(':'), QLatin1Char('_'));
1356+
QString result = name.replace(notAllowedChars, QLatin1String("_"));
1357+
QCOMPARE(result, expectedResult);
1358+
1359+
// objectName part can be max 72 chars in thread name
1360+
QCOMPARE(thread.threadName.left(72), expectedResult.left(72));
1361+
}
1362+
1363+
// objectName contains only invalid characters
1364+
{
1365+
testNamespace::TestThread thread;
1366+
QString name;
1367+
for (int i = 0; i < 0x20; i++) {
1368+
name.append(QLatin1Char(i));
1369+
}
1370+
for (int i = 0x7f; i < 0xff; i++) {
1371+
name.append(QLatin1Char(i));
1372+
}
1373+
1374+
thread.setObjectName(name);
1375+
thread.start();
1376+
thread.wait();
1377+
QCOMPARE(thread.runCalled, true);
1378+
1379+
QString expectedResult;
1380+
expectedResult.fill(QLatin1Char('_'), name.size());
1381+
QString result = name.replace(notAllowedChars, QLatin1String("_"));
1382+
QCOMPARE(result, expectedResult);
1383+
1384+
// objectName part can be max 72 chars in thread name
1385+
QCOMPARE(thread.threadName.left(72), expectedResult.left(72));
1386+
}
1387+
1388+
// objectName longer than max thread name length (80 chars)
1389+
{
1390+
testNamespace::TestThread thread;
1391+
QString name;
1392+
for (int i = 0; i < 0xff; i++) {
1393+
name.append(QLatin1Char(i));
1394+
}
1395+
1396+
thread.setObjectName(name);
1397+
thread.start();
1398+
thread.wait();
1399+
QCOMPARE(thread.runCalled, true);
1400+
}
1401+
1402+
// className contains not allowed characters (':')
1403+
{
1404+
testNamespace::TestThread thread;
1405+
thread.start();
1406+
thread.wait();
1407+
QCOMPARE(thread.runCalled, true);
1408+
QString className(QLatin1String(thread.metaObject()->className()));
1409+
QCOMPARE(className, QLatin1String("testNamespace::TestThread"));
1410+
1411+
QString expectedResult = className;
1412+
expectedResult = className.replace(QLatin1Char(':'), QLatin1Char('_'));
1413+
QString result = className.replace(notAllowedChars, QLatin1String("_"));
1414+
QCOMPARE(result, expectedResult);
1415+
1416+
QVERIFY(thread.threadName.contains(expectedResult));
1417+
}
1418+
}
1419+
#endif // Q_OS_SYMBIAN
12741420

12751421
QTEST_MAIN(tst_QThread)
12761422
#include "tst_qthread.moc"

0 commit comments

Comments
 (0)