diff options
author | Andrew Christian <andrew.christian@nokia.com> | 2012-04-12 08:36:32 -0400 |
---|---|---|
committer | Chris Craig <ext-chris.craig@nokia.com> | 2012-04-12 17:38:46 +0200 |
commit | 857e697d53196eca073ad7f9e7a3eeb3ddc70362 (patch) | |
tree | b0f7a59d0df50a0b5cae2167a5fb7539dff87f91 | |
parent | 78d09d5807985ab231b3f1224e2c262c50d9112c (diff) |
Added a test to verify that thread priorities are being set
Change-Id: I8d951852a7898c974a11b11a97011983ef0694c3
Reviewed-by: Martin Zielinski <martin.zielinski@nokia.com>
Reviewed-by: Chris Craig <ext-chris.craig@nokia.com>
-rw-r--r-- | src/core/procutils.cpp | 44 | ||||
-rw-r--r-- | src/core/procutils.h | 2 | ||||
-rw-r--r-- | tests/auto/processmanager/testClient/testClient.cpp | 28 | ||||
-rw-r--r-- | tests/auto/processmanager/testPrelaunch/testPrelaunch.cpp | 23 | ||||
-rw-r--r-- | tests/auto/processmanager/tst_processmanager.cpp | 60 |
5 files changed, 156 insertions, 1 deletions
diff --git a/src/core/procutils.cpp b/src/core/procutils.cpp index 7ecfd28..3e57b30 100644 --- a/src/core/procutils.cpp +++ b/src/core/procutils.cpp @@ -48,6 +48,7 @@ #include <errno.h> #include <QFile> +#include <QDir> #include <QFileInfo> #include <QLocalSocket> #include <QDebug> @@ -425,6 +426,49 @@ void ProcUtils::setPriority(pid_t pid, qint32 priority) qErrnoWarning(errno, "Failed to set process %d priority to %d", pid, priority); } +/*! + Return a count of the number of threads in a process + */ + +int ProcUtils::getThreadCount(pid_t pid) +{ +#if defined(Q_OS_LINUX) + QDir pdir(QString::fromLatin1("/proc/%1/task").arg(pid)); + return pdir.entryList(QDir::Dirs | QDir::NoDotAndDotDot).size(); +#endif + return 1; +} + +/*! + Return a list of priorities, one per thread in the process. This function + returns the "user visible" priority, a number from -20 to +19. + */ + +QList<qint32> ProcUtils::getThreadPriorities(pid_t pid) +{ + QList<qint32> plist; +#if defined(Q_OS_LINUX) + static QRegExp statFile(QStringLiteral("^(\\d+) \\(.*\\) [RSDZTW] (\\d+) (\\d+) (\\d+)(?: \\d+){11} (\\d+) (\\d+)")); + + QDir pdir(QString::fromLatin1("/proc/%1/task").arg(pid)); + foreach (const QString& entry, pdir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) { + QFile file(QString::fromLatin1("%1/%2/stat").arg(pdir.path()).arg(entry)); + if (!file.open(QIODevice::ReadOnly)) { + qWarning() << "Unable to read thread stat" << file.fileName(); + return plist; + } + QByteArray contents = file.readAll(); + if (statFile.indexIn(QString::fromLocal8Bit(contents)) != 0) { + qWarning("Did not match stat file expression"); + return plist; + } + plist << statFile.cap(6).toLong(); + } +#endif + return plist; +} + + #include "moc_procutils.cpp" QT_END_NAMESPACE_PROCESSMANAGER diff --git a/src/core/procutils.h b/src/core/procutils.h index 68008e7..0c89226 100644 --- a/src/core/procutils.h +++ b/src/core/procutils.h @@ -112,6 +112,8 @@ public: static void sendSignalToProcess(pid_t pid, int sig); static void setPriority(pid_t pid, qint32 priority); + static int getThreadCount(pid_t pid); + static QList<qint32> getThreadPriorities(pid_t pid); }; QT_END_NAMESPACE_PROCESSMANAGER diff --git a/tests/auto/processmanager/testClient/testClient.cpp b/tests/auto/processmanager/testClient/testClient.cpp index 17cde87..28c6f74 100644 --- a/tests/auto/processmanager/testClient/testClient.cpp +++ b/tests/auto/processmanager/testClient/testClient.cpp @@ -43,6 +43,8 @@ #include <string.h> #include <signal.h> #include <stdio.h> +#include <pthread.h> +#include <stdlib.h> const int kBufSize = 100; @@ -74,11 +76,21 @@ ssize_t readline(char *buffer, int max_len) return len; } +void * work(void *) +{ + while (1) + sleep(1); + pthread_exit((void *)0); +} + static char tough[] = "tough\n"; +const int kNumThreads = 4; int main(int argc, char **argv) { + pthread_t thread[kNumThreads]; + for (int i = 1 ; i < argc ; i++) { if (!strcmp(argv[i], "-noterm")) { struct sigaction action; @@ -91,9 +103,21 @@ main(int argc, char **argv) if (writeline(tough, strlen(tough)) < 0) return 3; } + else if (!strcmp(argv[i], "-threads")) { + pthread_attr_t attr; + pthread_attr_init(&attr); + for (int j = 0 ; j < kNumThreads ; j++) { + int result = pthread_create(&thread[j], &attr, work, (void *)j); + if (result) { + printf("Error in pthread_created: %d\n", result); + return 3; + } + } + pthread_attr_destroy(&attr); + } } - char buffer[kBufSize+1]; + char buffer[kBufSize+1]; while (1) { ssize_t count = readline(buffer, kBufSize); if (count < 0) @@ -110,4 +134,6 @@ main(int argc, char **argv) if (result < 0) return 2; } + + pthread_exit(NULL); } diff --git a/tests/auto/processmanager/testPrelaunch/testPrelaunch.cpp b/tests/auto/processmanager/testPrelaunch/testPrelaunch.cpp index 8de5b9a..a8b5138 100644 --- a/tests/auto/processmanager/testPrelaunch/testPrelaunch.cpp +++ b/tests/auto/processmanager/testPrelaunch/testPrelaunch.cpp @@ -47,6 +47,7 @@ #include "processinfo.h" #include <signal.h> #include <stdio.h> +#include <pthread.h> #if defined(Q_OS_LINUX) #include <sys/types.h> @@ -156,9 +157,19 @@ private: int count; }; +const int kNumThreads = 4; +void * work(void *) +{ + while (1) + sleep(1); + pthread_exit((void *)0); +} + int main(int argc, char **argv) { + pthread_t thread[kNumThreads]; + QCoreApplication app(argc, argv); QStringList args = QCoreApplication::arguments(); QString progname = args.takeFirst(); @@ -177,6 +188,18 @@ main(int argc, char **argv) } qDebug() << "tough"; } + else if (arg == QStringLiteral("-threads")) { + pthread_attr_t attr; + pthread_attr_init(&attr); + for (int j = 0 ; j < kNumThreads ; j++) { + int result = pthread_create(&thread[j], &attr, work, (void *)j); + if (result) { + printf("Error in pthread_created: %d\n", result); + return 3; + } + } + pthread_attr_destroy(&attr); + } } Container c; diff --git a/tests/auto/processmanager/tst_processmanager.cpp b/tests/auto/processmanager/tst_processmanager.cpp index b62addb..b586ff6 100644 --- a/tests/auto/processmanager/tst_processmanager.cpp +++ b/tests/auto/processmanager/tst_processmanager.cpp @@ -54,6 +54,7 @@ #include "pipeprocessbackendfactory.h" #include "socketprocessbackendfactory.h" #include "timeoutidledelegate.h" +#include "procutils.h" #include <signal.h> @@ -165,6 +166,19 @@ static void waitForTimeout(int timeout=5000) } } +static void waitForThreadCount(Q_PID pid, int count, int timeout=5000) +{ + QTime stopWatch; + stopWatch.start(); + forever { + if (ProcUtils::getThreadCount(pid) == count) + break; + if (stopWatch.elapsed() >= timeout) + QFAIL("Timed out waiting for thread count"); + QTestEventLoop::instance().enterLoop(1); + } +} + static void waitForInternalProcess(ProcessBackendManager *manager, int num=1, int timeout=5000) { QObject::connect(manager, SIGNAL(internalProcessesChanged()), @@ -960,6 +974,7 @@ private slots: void preforkLauncherOomChangeAfter() { preforkLauncherTest(oomChangeAfterClient); } void prelaunchChildAbort(); + void prelaunchThreadPriority(); void prelaunchWaitIdleTest(); void prelaunchForPipeLauncherIdle(); @@ -1013,6 +1028,51 @@ void tst_ProcessManager::prelaunchChildAbort() delete manager; } +#include <sys/time.h> +#include <sys/resource.h> + +void tst_ProcessManager::prelaunchThreadPriority() +{ + ProcessBackendManager *manager = new ProcessBackendManager; + TimeoutIdleDelegate *delegate = new TimeoutIdleDelegate; + delegate->setIdleInterval(250); + manager->setIdleDelegate(delegate); + + ProcessInfo info; + info.setValue("program", "testPrelaunch/testPrelaunch"); + info.setValue("arguments", QStringList() << "-threads"); + info.setValue("priority", 19); + PrelaunchProcessBackendFactory *factory = new PrelaunchProcessBackendFactory; + factory->setProcessInfo(info); + manager->addFactory(factory); + + // Start the prelaunch process and verify that all threads + // have been created and are at the correct priority + waitForInternalProcess(manager); + Q_PID pid = manager->internalProcesses().at(0); + waitForThreadCount(pid, 5); + foreach (qint32 priority, ProcUtils::getThreadPriorities(pid)) + QCOMPARE(priority, 19); + + info.setValue("priority", 5); + ProcessBackend *process = manager->create(info); + QVERIFY(process); + + Spy spy(process); + process->start(); + spy.waitStart(); + verifyRunning(process); + QCOMPARE(process->actualPriority(), 5); + foreach (qint32 priority, ProcUtils::getThreadPriorities(process->pid())) + QCOMPARE(priority, 5); + + writeJson(process, "stop"); + spy.waitFinished(); + cleanupProcess(process); + + delete manager; +} + void tst_ProcessManager::prelaunchWaitIdleTest() { ProcessBackendManager *manager = new ProcessBackendManager; |