[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-core-devel
Subject: OOM-killer prevention for master kdeinit process
From: Lubos Lunak <l.lunak () suse ! cz>
Date: 2006-08-02 13:09:43
Message-ID: 200608021509.43918.l.lunak () suse ! cz
[Download RAW message or body]
Hello,
short summary: Out Of Memory handling on Linux sucks, KDE can suffer badly
from it, kernel devels are unable to do anything about it, so let's again
work around things ourselves.
Reading for this is
http://www.lugroma.org/contenuti/eventi/LinuxDay2005/atti/Arcangeli-MemoryManagementKernel26.pdf .
Only pages 8-11 are relevant, pages after that are unrelated, pages before
that are either not really interesting or not true as long as KDE is
concerned - somehow I get the impression that OOM-handling is worse and worse
as the time goes (ah, and yes, I really hate it, just in case that's not
obvious). Anyway, to the point:
Run this:
ls /proc/*/oom_score | grep -v self | sed 's/\(.*\)\/\(.*\)/echo -n "\1 ";
echo -n "`cat \1\/\2 2>\/dev\/null` "; readlink \1\/exe || echo/'| sh |
sort -nr +1
That gives lines with </proc/pid> <likelyhood to be oom-killed> <binary>.
Run "pstree -p" and compare it with the top of the list. The very first item
that's going to be killed when running out of memory is going to be the
master kdeinit process, i.e. the tiny thingy that is linked against our basic
libraries which we use for launching apps. The reason why it's going to be
killed the first is that OOM-killing has some "smart" heuristic that counts
also all child processes into parent's score (it's mentioned in the paper)
and since this process launches almost all KDE processes it gets the sum of
almost whole KDE. No wonder it almost always wins the first place in the
list. In fact, since the killing first kills all children of the "offending"
process, that means that before memory is reclaimed to get out of OOM,
various processes like klauncher or kwin are killed -> KDE is pretty
unusable.
We've already tried to make kernel developers turn that off, change it in
order not to cause this kdeinit problem or at least give a better way to
exclude kdeinit than to echo as root to somewhere in /proc, to no avail
(because a good OOM-killer is apparently nothing trivial and also because
kernel developers have funny ideas about userspace). So we somewhere need to
do something like "echo -10 > /proc/<pid_of_kdeinit>/oom_adjust" as root when
running on Linux ( -10 means the score will be multiplied by 2^-10, i.e.
divided by 1024 ; given that kdeinit is very unlikely to go haywire that
seems pretty safe).
Now, who's the setuid guru here :)? Is the attached (KDE3) patch ok? I'd
prefer not to have security people going after me. The setuid stuff is copied
from artswrapper, the privileges are dropped immediately so I hope there's no
problem.
PS: Just in case somebody wonders why I hate OOM handling on Linux so much
then the answer is that my 1G RAM work machine with no swap at all being
trashed to death is probably the top reason why I reboot it (not that I
reboot that often otherwise).
--
Lubos Lunak
KDE developer
---------------------------------------------------------------------
SuSE CR, s.r.o. e-mail: l.lunak@suse.cz , l.lunak@kde.org
Drahobejlova 27 tel: +420 2 9654 2373
190 00 Praha 9 fax: +420 2 9654 2374
Czech Republic http://www.suse.cz/
["kinit.patch" (text/x-diff)]
--- kinit/kinit.cpp.sav 2006-05-24 18:34:48.000000000 +0200
+++ kinit/kinit.cpp 2006-08-02 15:07:33.000000000 +0200
@@ -1654,6 +1654,27 @@ int main(int argc, char **argv, char **e
int keep_running = 1;
int new_startup = 0;
d.suicide = false;
+
+#ifdef __linux__
+/* prevent getting killed by bad heuristic in Linux OOM-killer and drop root \
privileges */ + FILE* procfile = fopen( "/proc/self/oom_adj", "w" );
+ if( procfile ) {
+ fprintf( procfile, "-10" );
+ fclose( procfile );
+ }
+ if (geteuid() != getuid())
+ {
+#if defined (HAVE_SETEUID) && !defined (HAVE_SETEUID_FAKE)
+ seteuid(getuid());
+#else
+ setreuid(-1, getuid());
+#endif
+ if (geteuid() != getuid()) {
+ perror("setuid()");
+ exit(1);
+ }
+ }
+#endif
/** Save arguments first... **/
char **safe_argv = (char **) malloc( sizeof(char *) * argc);
--- kinit/Makefile.am.sav 2005-09-29 21:31:28.000000000 +0200
+++ kinit/Makefile.am 2006-08-02 14:58:11.000000000 +0200
@@ -77,6 +77,14 @@ shell.o: wrapper.c
dummy.cpp:
echo > dummy.cpp
+if KDEINIT_SETUID
+# kdeinit needs to be installed setuid root on Linux
+install-exec-hook:
+ @(chown 0 $(DESTDIR)$(bindir)/kdeinit && chmod 4755 $(DESTDIR)$(bindir)/kdeinit) || \
echo "Please make kdeinit setuid root" >&2 + @echo ""
+ @echo "kdeinit is by default installed on Linux with a set SETUID root bit!"
+ @echo "This is needed to prevent it from being killed by a bad heuristic in the \
OOM-killer when running out of memory." + @echo ""
+endif
include $(top_srcdir)/admin/Doxyfile.am
-
--- kinit/configure.in.in.sav 2005-05-04 12:52:23.000000000 +0200
+++ kinit/configure.in.in 2006-08-02 14:57:00.000000000 +0200
@@ -43,3 +43,15 @@ if test -n "$KDEINIT_FONTCONFIG"; then
AC_DEFINE(KDEINIT_USE_FONTCONFIG,1,[Use FontConfig in kdeinit])
fi
AC_SUBST(KDEINIT_XFT_INCLUDES)
+
+AC_MSG_CHECKING(whether to make kdeinit setuid root in order to protect it from bad \
Linux OOM-killer) +kdeinit_setuid=
+case $target_os in
+ linux*)
+ AC_MSG_RESULT(yes)
+ kdeinit_setuid=1
+ ;;
+ *) AC_MSG_RESULT(no)
+ ;;
+esac
+AM_CONDITIONAL(KDEINIT_SETUID, test -n "$kdeinit_setuid" )
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic