summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Christian <andrew.christian@nokia.com>2012-04-12 08:36:32 -0400
committerChris Craig <ext-chris.craig@nokia.com>2012-04-12 17:38:46 +0200
commit857e697d53196eca073ad7f9e7a3eeb3ddc70362 (patch)
treeb0f7a59d0df50a0b5cae2167a5fb7539dff87f91
parent78d09d5807985ab231b3f1224e2c262c50d9112c (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.cpp44
-rw-r--r--src/core/procutils.h2
-rw-r--r--tests/auto/processmanager/testClient/testClient.cpp28
-rw-r--r--tests/auto/processmanager/testPrelaunch/testPrelaunch.cpp23
-rw-r--r--tests/auto/processmanager/tst_processmanager.cpp60
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;