summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Christian <andrew.christian@nokia.com>2012-02-02 09:33:38 -0500
committerChris Craig <ext-chris.craig@nokia.com>2012-02-02 22:54:36 +0100
commitc103fef8e03c91679778d731d70b058674c6c737 (patch)
tree89e27f30986824dafe8132d7afc9373c39533d73
parent3621dfe4098bb550a91517e641deecaeb08c780f (diff)
Updated oom adjustment. Fixed test cases to work on Linux and MacOS
Change-Id: I71d2544bc883fed759dab5e33d041bf66f1369da Reviewed-by: Chris Craig <ext-chris.craig@nokia.com>
-rw-r--r--src/core/core-lib.pri11
-rw-r--r--src/core/procutils.cpp52
-rw-r--r--src/core/procutils.h3
-rw-r--r--src/core/remoteprocessbackend.cpp7
-rw-r--r--src/core/unixprocessbackend.cpp19
-rw-r--r--src/launcher/pipelauncher.cpp2
-rw-r--r--tests/auto/processmanager/tst_processmanager.cpp85
7 files changed, 159 insertions, 20 deletions
diff --git a/src/core/core-lib.pri b/src/core/core-lib.pri
index 361c8c8..e6540f4 100644
--- a/src/core/core-lib.pri
+++ b/src/core/core-lib.pri
@@ -20,12 +20,8 @@ PUBLIC_HEADERS += \
$$PWD/standardprocessbackend.h \
$$PWD/prelaunchprocessbackend.h \
$$PWD/remoteprocessbackend.h \
- $$PWD/processmanager-global.h
-
-*linux* {
- PUBLIC_HEADERS += $$PWD/procutils.h
- SOURCES += $$PWD/procutils.cpp
-}
+ $$PWD/processmanager-global.h \
+ $$PWD/procutils.h
HEADERS += \
$$PUBLIC_HEADERS \
@@ -49,4 +45,5 @@ SOURCES += \
$$PWD/remoteprocessbackend.cpp \
$$PWD/remoteprocessbackendfactory.cpp \
$$PWD/pipeprocessbackendfactory.cpp \
- $$PWD/socketprocessbackendfactory.cpp
+ $$PWD/socketprocessbackendfactory.cpp \
+ $$PWD/procutils.cpp
diff --git a/src/core/procutils.cpp b/src/core/procutils.cpp
index f6965b3..484d57f 100644
--- a/src/core/procutils.cpp
+++ b/src/core/procutils.cpp
@@ -58,22 +58,23 @@ ProcUtils::ProcUtils()
QString ProcUtils::execNameForPid(qint64 pid)
{
+#if defined(Q_OS_LINUX)
enum { BUFFERSIZE = 1024 };
char buf[BUFFERSIZE];
QString fn = QLatin1String("/proc/") + QString::number(pid).toLatin1() + QLatin1String("/exe");
ssize_t len = readlink(fn.toLatin1(), buf, sizeof(buf) - 1);
-
if (len != -1) {
buf[len] = '\0';
- } else {
- return QString();
+ return QString(buf);
}
-
- return QString(buf);
+#endif
+ return QString();
}
qint64 ProcUtils::ppidForPid(pid_t pid)
{
+ int ppid = 0;
+#if defined(Q_OS_LINUX)
QFile statFile(QLatin1String("/proc/") + QString::number(pid) + "/stat");
statFile.open(QIODevice::ReadOnly);
@@ -81,15 +82,16 @@ qint64 ProcUtils::ppidForPid(pid_t pid)
statFile.close();
// 954 (ofono-jdb-daemo) S 1
int readPid = 0;
- int ppid = 0;
char strDummy[64];
char state;
sscanf(contents.constData(), "%d %s %c %d %s", &readPid, strDummy, &state, &ppid, strDummy);
+#endif
return ppid;
}
qint64 ProcUtils::pidForFilename(const QString &filename)
{
+#if defined(Q_OS_LINUX)
QFile file(filename);
if (!file.exists())
return 0;
@@ -112,31 +114,65 @@ qint64 ProcUtils::pidForFilename(const QString &filename)
}
}
closedir(d);
+#endif
return 0;
}
qint64 ProcUtils::pidForLocalSocket(const QLocalSocket *socket)
{
+#if defined(Q_OS_LINUX)
if (socket) {
struct ucred cr;
socklen_t len = sizeof(struct ucred);
int r = ::getsockopt(socket->socketDescriptor(), SOL_SOCKET, SO_PEERCRED, &cr, &len);
- if (r == 0) {
+ if (r == 0)
return (qint64)cr.pid;
- }
}
+#endif
return 0;
}
QByteArray ProcUtils::cmdlineForPid(qint64 pid)
{
QByteArray cmdline;
+#if defined(Q_OS_LINUX)
if (pid) {
QFile file(QLatin1String("/proc/") + QString::number(pid) + QLatin1String("/cmdline"));
file.open(QIODevice::ReadOnly);
cmdline = file.readAll();
}
return cmdline;
+#endif
}
+qint32 ProcUtils::oomAdjustment(pid_t pid, bool *ok)
+{
+ if (ok)
+ *ok = false;
+#if defined(Q_OS_LINUX)
+ QFile file(QString::fromLatin1("/proc/%1/oom_score_adj").arg(pid));
+ if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ QByteArray ba = file.read(100);
+ ba.truncate(ba.count() - 1); // Drop the '\n' at the end
+ if (ba.count())
+ return ba.toInt(ok);
+ }
+#endif
+ return -1001;
+}
+
+bool ProcUtils::setOomAdjustment(pid_t pid, qint32 oomAdjustment)
+{
+#if defined(Q_OS_LINUX)
+ QFile file(QString::fromLatin1("/proc/%1/oom_score_adj").arg(pid));
+ if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
+ return false;
+ QByteArray value = QByteArray::number(oomAdjustment) + '\n';
+ if (file.write(value) == value.count())
+ return true;
+#endif
+ return false;
+}
+
+
QT_END_NAMESPACE_PROCESSMANAGER
diff --git a/src/core/procutils.h b/src/core/procutils.h
index 4fe5d6f..f40fea4 100644
--- a/src/core/procutils.h
+++ b/src/core/procutils.h
@@ -58,6 +58,9 @@ public:
static qint64 pidForFilename(const QString &filename);
static qint64 pidForLocalSocket(const QLocalSocket *socket);
static QByteArray cmdlineForPid(qint64 pid);
+
+ static qint32 oomAdjustment(pid_t pid, bool *ok=NULL);
+ static bool setOomAdjustment(pid_t pid, qint32 oomAdjustment);
};
QT_END_NAMESPACE_PROCESSMANAGER
diff --git a/src/core/remoteprocessbackend.cpp b/src/core/remoteprocessbackend.cpp
index b7a79f7..6ea130b 100644
--- a/src/core/remoteprocessbackend.cpp
+++ b/src/core/remoteprocessbackend.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "remoteprocessbackend.h"
+#include "procutils.h"
#include <sys/resource.h>
#include <errno.h>
#include <signal.h>
@@ -141,7 +142,11 @@ void RemoteProcessBackend::setDesiredPriority(qint32 priority)
qint32 RemoteProcessBackend::actualOomAdjustment() const
{
if (m_pid != -1) {
- // ### TODO: Read correctly from /proc/<pid>/oom_score_adj
+ bool ok;
+ qint32 result = ProcUtils::oomAdjustment(m_pid, &ok);
+ if (ok)
+ return result;
+ qWarning() << "Unable to read oom adjustment for" << m_pid;
}
return ProcessBackend::actualOomAdjustment();
}
diff --git a/src/core/unixprocessbackend.cpp b/src/core/unixprocessbackend.cpp
index de7a9c5..b019ebc 100644
--- a/src/core/unixprocessbackend.cpp
+++ b/src/core/unixprocessbackend.cpp
@@ -41,9 +41,11 @@
#include "unixprocessbackend.h"
#include "unixsandboxprocess.h"
+#include "procutils.h"
#include <sys/resource.h>
#include <errno.h>
#include <QDebug>
+#include <QFile>
QT_BEGIN_NAMESPACE_PROCESSMANAGER
@@ -119,8 +121,14 @@ void UnixProcessBackend::setDesiredPriority(qint32 priority)
qint32 UnixProcessBackend::actualOomAdjustment() const
{
+ // ### TODO: What if m_process doesn't have a valid PID yet?
+
if (m_process) {
- // ### TODO: Read correctly from /proc/<pid>/oom_score_adj
+ bool ok;
+ qint32 result = ProcUtils::oomAdjustment(m_process->pid(), &ok);
+ if (ok)
+ return result;
+ qWarning() << "Unable to read oom adjustment for" << m_process->pid();
}
return ProcessBackend::actualOomAdjustment();
}
@@ -133,7 +141,8 @@ void UnixProcessBackend::setDesiredOomAdjustment(qint32 oomAdjustment)
{
ProcessBackend::setDesiredOomAdjustment(oomAdjustment);
if (m_process) {
- // ### Write to /proc/<pid>/oom_score_adj
+ if (!ProcUtils::setOomAdjustment(m_process->pid(), oomAdjustment))
+ qWarning() << "Unable to set oom adjustment for" << m_process->pid();
}
}
@@ -240,7 +249,11 @@ void UnixProcessBackend::handleProcessStarted()
{
if (m_info.contains("priority") && setpriority(PRIO_PROCESS, m_process->pid(), m_info.priority()))
qWarning() << "Failed to set process priority at startup from " << actualPriority() <<
- "to" << m_info.priority() << " : errno = " << errno;
+ "to" << m_info.priority() << " : errno = " << errno;
+ if (m_info.contains("oomAdjustment") &&
+ !ProcUtils::setOomAdjustment(m_process->pid(), m_info.oomAdjustment()))
+ qWarning() << "Failed to set process oom score at startup from " << actualOomAdjustment() <<
+ "to" << m_info.oomAdjustment();
}
/*!
Override this in subclasses. Make sure you call the parent class with \a error.
diff --git a/src/launcher/pipelauncher.cpp b/src/launcher/pipelauncher.cpp
index 45dec45..d3bcf6e 100644
--- a/src/launcher/pipelauncher.cpp
+++ b/src/launcher/pipelauncher.cpp
@@ -98,7 +98,7 @@ void PipeLauncher::inReady(int fd)
m_inbuf = m_inbuf.mid(message_size);
QJsonObject message = QJsonDocument::fromBinaryData(msg).object();
if (message.value("remote").toString() == "stop")
- deleteLater();
+ exit(0);
m_client->receive(message);
}
m_in->setEnabled(true);
diff --git a/tests/auto/processmanager/tst_processmanager.cpp b/tests/auto/processmanager/tst_processmanager.cpp
index 788c143..043f48b 100644
--- a/tests/auto/processmanager/tst_processmanager.cpp
+++ b/tests/auto/processmanager/tst_processmanager.cpp
@@ -490,6 +490,71 @@ static void priorityChangeAfterClient(ProcessBackendManager *manager, ProcessInf
delete process;
}
+#if defined(Q_OS_LINUX)
+
+static void waitForOom(ProcessBackend *process, int oom, int timeout=5000)
+{
+ QTime stopWatch;
+ stopWatch.start();
+ forever {
+ if (process->actualOomAdjustment() == oom)
+ break;
+ QTestEventLoop::instance().enterLoop(1);
+ if (stopWatch.elapsed() >= timeout)
+ QFAIL("Timed out");
+ }
+}
+
+static void oomChangeBeforeClient(ProcessBackendManager *manager, ProcessInfo info, CommandFunc func)
+{
+ info.setOomAdjustment(500);
+ ProcessBackend *process = manager->create(info);
+ QVERIFY(process);
+
+ Spy spy(process);
+ process->start();
+ spy.waitStart();
+ QVERIFY(process->state() == QProcess::Running);
+ QCOMPARE(process->actualOomAdjustment(), 500);
+
+ func(process, "stop");
+ spy.waitFinished();
+ spy.check(1,0,1,3);
+ spy.checkExitCode(0);
+ spy.checkExitStatus(QProcess::NormalExit);
+
+ QVERIFY(process->state() == QProcess::NotRunning);
+ QVERIFY(process->parent() == NULL);
+ delete process;
+}
+
+static void oomChangeAfterClient(ProcessBackendManager *manager, ProcessInfo info, CommandFunc func)
+{
+ ProcessBackend *process = manager->create(info);
+ QVERIFY(process);
+ QVERIFY(process->state() == QProcess::NotRunning);
+
+ Spy spy(process);
+ process->start();
+ spy.waitStart();
+ QVERIFY(process->state() == QProcess::Running);
+
+ process->setDesiredOomAdjustment(499);
+ waitForOom(process, 499);
+
+ func(process, "stop");
+ spy.waitFinished();
+ spy.check(1,0,1,3);
+ spy.checkExitCode(0);
+ spy.checkExitStatus(QProcess::NormalExit);
+
+ QVERIFY(process->state() == QProcess::NotRunning);
+ QVERIFY(process->parent() == NULL);
+ delete process;
+}
+
+#endif // defined(Q_OS_LINUX)
+
typedef void (*clientFunc)(ProcessBackendManager *, ProcessInfo, CommandFunc);
@@ -597,6 +662,10 @@ private slots:
void standardEcho() { standardFactoryTest(echoClient); }
void standardPriorityChangeBefore() { standardFactoryTest(priorityChangeBeforeClient); }
void standardPriorityChangeAfter() { standardFactoryTest(priorityChangeAfterClient); }
+#if defined(Q_OS_LINUX)
+ void standardOomChangeBefore() { standardFactoryTest(oomChangeBeforeClient); }
+ void standardOomChangeAfter() { standardFactoryTest(oomChangeAfterClient); }
+#endif
void prelaunchStartAndStop() { prelaunchFactoryTest(startAndStopClient); }
void prelaunchStartAndKill() { prelaunchFactoryTest(startAndKillClient); }
@@ -604,6 +673,10 @@ private slots:
void prelaunchEcho() { prelaunchFactoryTest(echoClient); }
void prelaunchPriorityChangeBefore() { prelaunchFactoryTest(priorityChangeBeforeClient); }
void prelaunchPriorityChangeAfter() { prelaunchFactoryTest(priorityChangeAfterClient); }
+#if defined(Q_OS_LINUX)
+ void prelaunchOomChangeBefore() { prelaunchFactoryTest(oomChangeBeforeClient); }
+ void prelaunchOomChangeAfter() { prelaunchFactoryTest(oomChangeAfterClient); }
+#endif
void prelaunchRestrictedStartAndStop() { prelaunchRestrictedTest(startAndStopClient); }
void prelaunchRestrictedStartAndKill() { prelaunchRestrictedTest(startAndKillClient); }
@@ -611,6 +684,10 @@ private slots:
void prelaunchRestrictedEcho() { prelaunchRestrictedTest(echoClient); }
void prelaunchRestrictedPriorityChangeBefore() { prelaunchRestrictedTest(priorityChangeBeforeClient); }
void prelaunchRestrictedPriorityChangeAfter() { prelaunchRestrictedTest(priorityChangeAfterClient); }
+#if defined(Q_OS_LINUX)
+ void prelaunchRestrictedOomChangeBefore() { prelaunchRestrictedTest(oomChangeBeforeClient); }
+ void prelaunchRestrictedOomChangeAfter() { prelaunchRestrictedTest(oomChangeAfterClient); }
+#endif
void pipeLauncherStartAndStop() { pipeLauncherTest(startAndStopClient); }
void pipeLauncherStartAndKill() { pipeLauncherTest(startAndKillClient); }
@@ -618,6 +695,10 @@ private slots:
void pipeLauncherEcho() { pipeLauncherTest(echoClient); }
void pipeLauncherPriorityChangeBefore() { pipeLauncherTest(priorityChangeBeforeClient); }
void pipeLauncherPriorityChangeAfter() { pipeLauncherTest(priorityChangeAfterClient); }
+#if defined(Q_OS_LINUX)
+ void pipeLauncherOomChangeBefore() { pipeLauncherTest(oomChangeBeforeClient); }
+ void pipeLauncherOomChangeAfter() { pipeLauncherTest(oomChangeAfterClient); }
+#endif
void socketLauncherStartAndStop() { socketLauncherTest(startAndStopClient); }
void socketLauncherStartAndKill() { socketLauncherTest(startAndKillClient); }
@@ -625,6 +706,10 @@ private slots:
void socketLauncherEcho() { socketLauncherTest(echoClient); }
void socketLauncherPriorityChangeBefore() { socketLauncherTest(priorityChangeBeforeClient); }
void socketLauncherPriorityChangeAfter() { socketLauncherTest(priorityChangeAfterClient); }
+#if defined(Q_OS_LINUX)
+ void socketLauncherOomChangeBefore() { socketLauncherTest(oomChangeBeforeClient); }
+ void socketLauncherOomChangeAfter() { socketLauncherTest(oomChangeAfterClient); }
+#endif
void frontend();
void subclassFrontend();