r21398 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r21397‎ | r21398 | r21399 >
Date:01:19, 20 April 2007
Author:river
Status:old
Tags:
Comment:
- debianise
- configuration file instead of command line
- mail message should be a file instead of hardcoded
- write pidfile at startup
Modified paths:
  • /trunk/tools/slayerd/Makefile (modified) (history)
  • /trunk/tools/slayerd/debian (added) (history)
  • /trunk/tools/slayerd/debian/changelog (added) (history)
  • /trunk/tools/slayerd/debian/compat (added) (history)
  • /trunk/tools/slayerd/debian/control (added) (history)
  • /trunk/tools/slayerd/debian/copyright (added) (history)
  • /trunk/tools/slayerd/debian/default (added) (history)
  • /trunk/tools/slayerd/debian/dirs (added) (history)
  • /trunk/tools/slayerd/debian/docs (added) (history)
  • /trunk/tools/slayerd/debian/files (added) (history)
  • /trunk/tools/slayerd/debian/init.d (added) (history)
  • /trunk/tools/slayerd/debian/postinst (added) (history)
  • /trunk/tools/slayerd/debian/postrm (added) (history)
  • /trunk/tools/slayerd/debian/preinst (added) (history)
  • /trunk/tools/slayerd/debian/prerm (added) (history)
  • /trunk/tools/slayerd/debian/rules (added) (history)
  • /trunk/tools/slayerd/debian/slayerd.postinst.debhelper (added) (history)
  • /trunk/tools/slayerd/debian/slayerd.postrm.debhelper (added) (history)
  • /trunk/tools/slayerd/debian/slayerd.prerm.debhelper (added) (history)
  • /trunk/tools/slayerd/debian/slayerd.substvars (added) (history)
  • /trunk/tools/slayerd/mailmessage (added) (history)
  • /trunk/tools/slayerd/slayerd.cc (modified) (history)
  • /trunk/tools/slayerd/slayerd.conf.example (added) (history)

Diff [purge]

Index: trunk/tools/slayerd/slayerd.conf.example
@@ -0,0 +1,23 @@
 2+# Example configuration file for slayerd(8). This file is read
 3+# before the command line options.
 4+
 5+# Maximum per-user memory limit; processes will be killed if the
 6+# user's memory use exceeds this limit. Given in MB.
 7+limit 500
 8+
 9+# Kill threshold. Processes will be killed until the user's memory
 10+# use drops below this number, also in MB.
 11+thresh 300
 12+
 13+# Time to wait between checks, in seconds.
 14+delay 10
 15+
 16+# Ignore certain users. root (UID 0) is always exempt.
 17+#exempt adminuser
 18+#exempt gooduser
 19+
 20+# Command to send mail.
 21+sendmail /usr/lib/sendmail -oi -bm --
 22+
 23+# File to store PID in.
 24+#pidfile /var/run/slayerd.pid
Index: trunk/tools/slayerd/debian/slayerd.substvars
@@ -0,0 +1 @@
 2+shlibs:Depends=libboost-filesystem1.33.1, libc6 (>= 2.3.5-1), libgcc1 (>= 1:4.1.1-12), libstdc++6 (>= 4.1.1-12)
Index: trunk/tools/slayerd/debian/dirs
@@ -0,0 +1 @@
 2+usr/sbin
Index: trunk/tools/slayerd/debian/files
@@ -0,0 +1 @@
 2+slayerd_1.0-1_amd64.deb admin extra
Index: trunk/tools/slayerd/debian/copyright
@@ -0,0 +1,10 @@
 2+This package was debianized by River Tarnell <river@attenuate.org> on
 3+Thu, 19 Apr 2007 21:55:19 +0000.
 4+
 5+Copyright: 2007, River Tarnell.
 6+
 7+License:
 8+ Permission is granted to anyone to use this software for any purpose,
 9+ including commercial applications, and to alter it and redistribute it
 10+ freely. This software is provided 'as-is', without any express or implied
 11+ warranty.
Index: trunk/tools/slayerd/debian/slayerd.postinst.debhelper
@@ -0,0 +1,10 @@
 2+# Automatically added by dh_installinit
 3+if [ -x "/etc/init.d/slayerd" ]; then
 4+ update-rc.d slayerd defaults >/dev/null
 5+ if [ -x "`which invoke-rc.d 2>/dev/null`" ]; then
 6+ invoke-rc.d slayerd start || exit $?
 7+ else
 8+ /etc/init.d/slayerd start || exit $?
 9+ fi
 10+fi
 11+# End automatically added section
Index: trunk/tools/slayerd/debian/slayerd.postrm.debhelper
@@ -0,0 +1,5 @@
 2+# Automatically added by dh_installinit
 3+if [ "$1" = "purge" ] ; then
 4+ update-rc.d slayerd remove >/dev/null || exit $?
 5+fi
 6+# End automatically added section
Index: trunk/tools/slayerd/debian/slayerd.prerm.debhelper
@@ -0,0 +1,9 @@
 2+# Automatically added by dh_installinit
 3+if [ -x "/etc/init.d/slayerd" ]; then
 4+ if [ -x "`which invoke-rc.d 2>/dev/null`" ]; then
 5+ invoke-rc.d slayerd stop || exit $?
 6+ else
 7+ /etc/init.d/slayerd stop || exit $?
 8+ fi
 9+fi
 10+# End automatically added section
Index: trunk/tools/slayerd/debian/control
@@ -0,0 +1,14 @@
 2+Source: slayerd
 3+Section: admin
 4+Priority: extra
 5+Maintainer: River Tarnell <river@attenuate.org>
 6+Build-Depends: debhelper (>= 5)
 7+Standards-Version: 3.7.2
 8+
 9+Package: slayerd
 10+Architecture: any
 11+Depends: ${shlibs:Depends}, ${misc:Depends}
 12+Description: Kill errant user processes
 13+ slayerd monitors the system for users using too much memory.
 14+ If any are found, their processes are trimmed to within acceptable
 15+ limits.
Index: trunk/tools/slayerd/debian/compat
@@ -0,0 +1 @@
 2+5
Index: trunk/tools/slayerd/debian/postinst
@@ -0,0 +1,6 @@
 2+#! /bin/sh
 3+
 4+set -e
 5+
 6+#DEBHELPER#
 7+
Property changes on: trunk/tools/slayerd/debian/postinst
___________________________________________________________________
Added: svn:executable
18 + *
Index: trunk/tools/slayerd/debian/default
@@ -0,0 +1,10 @@
 2+# Defaults for slayerd initscript
 3+# sourced by /etc/init.d/slayerd
 4+# installed at /etc/default/slayerd by the maintainer scripts
 5+
 6+#
 7+# This is a POSIX shell fragment
 8+#
 9+
 10+# Additional options that are passed to the daemon.
 11+DAEMON_OPTS=""
Index: trunk/tools/slayerd/debian/postrm
@@ -0,0 +1,6 @@
 2+#! /bin/sh
 3+
 4+set -e
 5+
 6+#DEBHELPER#
 7+
Property changes on: trunk/tools/slayerd/debian/postrm
___________________________________________________________________
Added: svn:executable
18 + *
Index: trunk/tools/slayerd/debian/preinst
@@ -0,0 +1,6 @@
 2+#! /bin/sh
 3+
 4+set -e
 5+
 6+#DEBHELPER#
 7+
Property changes on: trunk/tools/slayerd/debian/preinst
___________________________________________________________________
Added: svn:executable
18 + *
Index: trunk/tools/slayerd/debian/init.d
@@ -0,0 +1,67 @@
 2+#! /bin/sh
 3+#
 4+# Written by Miquel van Smoorenburg <miquels@cistron.nl>.
 5+# Modified for Debian
 6+# by Ian Murdock <imurdock@gnu.ai.mit.edu>.
 7+#
 8+# Version: @(#)skeleton 1.9 26-Feb-2001 miquels@cistron.nl
 9+#
 10+
 11+PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
 12+DAEMON=/usr/sbin/slayerd
 13+NAME=slayerd
 14+DESC="process slayed (slayerd)"
 15+
 16+test -x $DAEMON || exit 0
 17+
 18+# Include defaults if available
 19+if [ -f /etc/default/slayerd ] ; then
 20+ . /etc/default/slayerd
 21+fi
 22+
 23+set -e
 24+
 25+[ -f /etc/slayerd/slayerd.conf ] || exit 0
 26+
 27+case "$1" in
 28+ start)
 29+ echo -n "Starting $DESC: "
 30+ start-stop-daemon --start --quiet --pidfile /var/run/$NAME.pid \
 31+ --exec $DAEMON -- $DAEMON_OPTS
 32+ echo "$NAME."
 33+ ;;
 34+ stop)
 35+ echo -n "Stopping $DESC: "
 36+ start-stop-daemon --oknodo --stop --quiet --pidfile /var/run/$NAME.pid \
 37+ --exec $DAEMON
 38+ echo "$NAME."
 39+ ;;
 40+ force-reload)
 41+ #
 42+ # If the "reload" option is implemented, move the "force-reload"
 43+ # option to the "reload" entry above. If not, "force-reload" is
 44+ # just the same as "restart" except that it does nothing if the
 45+ # daemon isn't already running.
 46+ # check wether $DAEMON is running. If so, restart
 47+ start-stop-daemon --stop --test --quiet --pidfile \
 48+ /var/run/$NAME.pid --exec $DAEMON \
 49+ && $0 restart \
 50+ || exit 0
 51+ ;;
 52+ restart)
 53+ echo -n "Restarting $DESC: "
 54+ start-stop-daemon --stop --quiet --pidfile \
 55+ /var/run/$NAME.pid --exec $DAEMON
 56+ sleep 1
 57+ start-stop-daemon --start --quiet --pidfile \
 58+ /var/run/$NAME.pid --exec $DAEMON -- $DAEMON_OPTS
 59+ echo "$NAME."
 60+ ;;
 61+ *)
 62+ N=/etc/init.d/$NAME
 63+ echo "Usage: $N {start|stop|restart|force-reload}" >&2
 64+ exit 1
 65+ ;;
 66+esac
 67+
 68+exit 0
Index: trunk/tools/slayerd/debian/prerm
@@ -0,0 +1,6 @@
 2+#! /bin/sh
 3+
 4+set -e
 5+
 6+#DEBHELPER#
 7+
Property changes on: trunk/tools/slayerd/debian/prerm
___________________________________________________________________
Added: svn:executable
18 + *
Index: trunk/tools/slayerd/debian/changelog
@@ -0,0 +1,6 @@
 2+slayerd (1.0-1) unstable; urgency=low
 3+
 4+ * Initial release
 5+
 6+ -- River Tarnell <river@attenuate.org> Thu, 19 Apr 2007 21:55:19 +0000
 7+
Index: trunk/tools/slayerd/debian/docs
Index: trunk/tools/slayerd/debian/rules
@@ -0,0 +1,60 @@
 2+#!/usr/bin/make -f
 3+
 4+CFLAGS = -Wall -g
 5+
 6+ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
 7+ CFLAGS += -O0
 8+else
 9+ CFLAGS += -O2
 10+endif
 11+
 12+configure: configure-stamp
 13+configure-stamp:
 14+ dh_testdir
 15+ touch configure-stamp
 16+
 17+
 18+build: build-stamp
 19+
 20+build-stamp: configure-stamp
 21+ dh_testdir
 22+ $(MAKE) PREFIX=/usr
 23+ touch $@
 24+
 25+clean:
 26+ dh_testdir
 27+ dh_testroot
 28+ rm -f build-stamp configure-stamp
 29+ -$(MAKE) clean
 30+ dh_clean
 31+
 32+install: build
 33+ dh_testdir
 34+ dh_testroot
 35+ dh_clean -k
 36+ dh_installdirs
 37+
 38+ $(MAKE) DESTDIR=$(CURDIR)/debian/slayerd PREFIX=/usr install
 39+
 40+binary-indep: build install
 41+
 42+binary-arch: build install
 43+ dh_testdir
 44+ dh_testroot
 45+ dh_installchangelogs
 46+ dh_installdocs
 47+ dh_installexamples
 48+ dh_installinit
 49+ dh_installman
 50+ dh_link
 51+ dh_strip
 52+ dh_compress
 53+ dh_fixperms
 54+ dh_installdeb
 55+ dh_shlibdeps
 56+ dh_gencontrol
 57+ dh_md5sums
 58+ dh_builddeb
 59+
 60+binary: binary-indep binary-arch
 61+.PHONY: build clean binary-indep binary-arch binary install configure
Property changes on: trunk/tools/slayerd/debian/rules
___________________________________________________________________
Added: svn:executable
162 + *
Index: trunk/tools/slayerd/mailmessage
@@ -0,0 +1,27 @@
 2+From: slayerd <slayerd@%hostname%>
 3+To: %user% <%user%@%hostname%>
 4+Subject: Excessive memory usage from your processes.
 5+Reply-To: root <root@%hostname%>
 6+
 7+This message was automatically generated by slayerd on %hostname%.
 8+
 9+Hello,
 10+
 11+One or more of your processes on the host %hostname%
 12+were exceeding the configured memory limit, which is %limit% megabytes.
 13+I have killed enough of your processes to bring your usage back to the
 14+threshold limit, which is %thresh% megabytes.
 15+
 16+These are the processes I killed:
 17+
 18+%processes%
 19+
 20+Your total memory usage is now %current% megabyte(s).
 21+
 22+Excessive memory usage is usually a symptom of a broken program. Please
 23+investigate the cause of the problem and fix it before you restart these
 24+processes.
 25+
 26+Regards,
 27+ slayerd (the process slayer)
 28+
Index: trunk/tools/slayerd/slayerd.cc
@@ -39,9 +39,28 @@
4040
4141 namespace {
4242 std::string PATH_PROC = "/proc";
43 - std::string SENDMAIL = "/usr/lib/sendmail";
 43+ std::string CONFFILE = "/etc/slayerd/slayerd.conf";
4444 }
4545
 46+struct config_t {
 47+ std::size_t limit;
 48+ std::size_t thresh;
 49+ int delay;
 50+ std::string mailmessage;
 51+ std::string sendmail;
 52+ std::string pidfile;
 53+ std::set<uid_t> exempt;
 54+
 55+ config_t()
 56+ : limit(0)
 57+ , thresh(0)
 58+ , delay(60)
 59+ , mailmessage(ETCDIR "/mailmessage")
 60+ , sendmail("/usr/lib/sendmail -oi -bm --")
 61+ , pidfile("/var/run/slayerd.pid")
 62+ {}
 63+} config;
 64+
4665 struct process {
4766 process(fs::path const &pth);
4867
@@ -188,14 +207,13 @@
189208
190209 void
191210 version(void) {
192 - std::cerr << "slayerd $Revision$\n";
 211+ std::cerr << "slayerd 1.0\n";
193212 std::cerr << "Copyright (C) 2007, River Tarnell <river@attenuate.org>.\n";
194213 }
195214
196215 void
197216 usage(void) {
198 - std::cerr <<
199 -"usage: slayerd [-vh] -l <limit> -t <thread> [-e <user>]\n"
 217+ std::cerr << "usage: slayerd [-fvh] [-c <conf>]\n"
200218 ;
201219 }
202220
@@ -208,10 +226,10 @@
209227 void
210228 sendmail(std::string const &username, std::string const &message)
211229 {
212 - std::string cmd = str(boost::format("%s -oi -bm -- %s") % SENDMAIL % username);
 230+ std::string cmd = str(boost::format("%s %s") % config.sendmail % username);
213231 FILE *p = popen(cmd.c_str(), "w");
214232 if (p == 0) {
215 - log(str(boost::format("cannot send mail using %s: %s") % SENDMAIL % std::strerror(errno)));
 233+ log(str(boost::format("cannot send mail using %s: %s") % config.sendmail % std::strerror(errno)));
216234 return;
217235 }
218236
@@ -219,55 +237,210 @@
220238 pclose(p);
221239 }
222240
 241+std::string
 242+replace_file(std::string const &filename, std::map<std::string, std::string> const &vars)
 243+{
 244+ std::string file;
 245+ std::string result;
 246+
 247+ std::ifstream f(filename.c_str());
 248+ if (!f) {
 249+ log(str(boost::format("cannot open %s: %s") % filename % std::strerror(errno)));
 250+ return "";
 251+ }
 252+
 253+ std::string line;
 254+ while (std::getline(f, line)) {
 255+ std::string::size_type i, j;
 256+ while ((i = line.find('%')) != std::string::npos) {
 257+ if ((j = line.find('%', i + 1)) == std::string::npos) {
 258+ result += line;
 259+ line = "";
 260+ break;
 261+ }
 262+
 263+ result += line.substr(0, i);
 264+ std::string var = line.substr(i + 1, j - i - 1);
 265+ std::map<std::string, std::string>::const_iterator it = vars.find(var);
 266+
 267+ if (it == vars.end()) {
 268+ result += line.substr(i);
 269+ line = "";
 270+ break;
 271+ }
 272+
 273+ result += it->second;
 274+ line = line.substr(j + 1);
 275+ }
 276+
 277+ result += line;
 278+ result += '\n';
 279+ }
 280+
 281+ return result;
 282+}
 283+
 284+bool
 285+configure(void)
 286+{
 287+ std::ifstream conffile(CONFFILE.c_str());
 288+ if (!conffile) {
 289+ std::string err = str(boost::format("cannot open %s: %s") % CONFFILE % std::strerror(errno));
 290+ std::cerr << err << '\n';
 291+ log(err);
 292+ return false;
 293+ }
 294+
 295+ std::string line;
 296+ int lineno = 0;
 297+ while (std::getline(conffile, line)) {
 298+ ++lineno;
 299+
 300+ if (line[0] == '#')
 301+ continue;
 302+ if (line.empty())
 303+ continue;
 304+
 305+ std::istringstream l(line);
 306+ std::string d;
 307+ if (!(l >> d))
 308+ continue;
 309+
 310+ if (d == "limit") {
 311+ if (!(l >> config.limit)) {
 312+ std::string err = str(boost::format("\"%s\", line %d: invalid limit") % CONFFILE % lineno);
 313+ std::cerr << err << '\n';
 314+ log(err);
 315+ return false;
 316+ }
 317+ config.limit *= 1024 * 1024;
 318+ } else if (d == "thresh") {
 319+ if (!(l >> config.thresh)) {
 320+ std::string err = str(boost::format("\"%s\", line %d: invalid threshold") % CONFFILE % lineno);
 321+ std::cerr << err << '\n';
 322+ log(err);
 323+ return false;
 324+ }
 325+ config.thresh *= 1024 * 1024;
 326+ } else if (d == "exempt") {
 327+ std::string username;
 328+ if (!(l >> username)) {
 329+ std::string err = str(boost::format("\"%s\", line %d: invalid username") % CONFFILE % lineno);
 330+ std::cerr << err << '\n';
 331+ log(err);
 332+ return false;
 333+ }
 334+
 335+ uid_t id = uid(username);
 336+ if (id == -1) {
 337+ std::string err = str(boost::format("\"%s\", line %d: user \"%s\" does not exist")
 338+ % CONFFILE % lineno % username);
 339+ std::cerr << err << '\n';
 340+ log(err);
 341+ return false;
 342+ }
 343+ config.exempt.insert(id);
 344+ } else if (d == "delay") {
 345+ if (!(l >> config.delay)) {
 346+ std::string err = str(boost::format("\"%s\", line %d: invalid delay") % CONFFILE % lineno);
 347+ std::cerr << err << '\n';
 348+ log(err);
 349+ return false;
 350+ }
 351+ } else if (d == "mailmessage") {
 352+ if (!(l >> config.mailmessage)) {
 353+ std::string err = str(boost::format("\"%s\", line %d: invalid mail message") % CONFFILE % lineno);
 354+ std::cerr << err << '\n';
 355+ log(err);
 356+ return false;
 357+ }
 358+ } else if (d == "sendmail") {
 359+ if (!(l >> config.sendmail)) {
 360+ std::string err = str(boost::format("\"%s\", line %d: invalid sendmail command") % CONFFILE % lineno);
 361+ std::cerr << err << '\n';
 362+ log(err);
 363+ return false;
 364+ }
 365+ } else if (d == "pidfile") {
 366+ if (!(l >> config.pidfile)) {
 367+ std::string err = str(boost::format("\"%s\", line %d: invalid pid file") % CONFFILE % lineno);
 368+ std::cerr << err << '\n';
 369+ log(err);
 370+ return false;
 371+ }
 372+ } else {
 373+ std::string err = str(boost::format("\"%s\", line %d: invalid directive") % CONFFILE % lineno);
 374+ std::cerr << err << '\n';
 375+ log(err);
 376+ return false;
 377+ }
 378+ }
 379+
 380+ return true;
 381+}
 382+
 383+void
 384+rmpidfile(void)
 385+{
 386+ unlink(config.pidfile.c_str());
 387+}
 388+
 389+void
 390+do_signal(int sig)
 391+{
 392+ rmpidfile();
 393+ _exit(0);
 394+}
 395+
 396+bool
 397+do_pidfile(void)
 398+{
 399+ {
 400+ std::ifstream pf(config.pidfile.c_str());
 401+ if (pf) {
 402+ std::string pid;
 403+ std::getline(pf, pid);
 404+ std::cerr << boost::format("slayerd already running (pid %d) or stale pidfile %s\n")
 405+ % pid % config.pidfile;
 406+ return false;
 407+ }
 408+ }
 409+
 410+ std::ofstream pf(config.pidfile.c_str());
 411+ if (!pf) {
 412+ std::cerr << boost::format("cannot open pidfile %s: %s\n")
 413+ % config.pidfile % std::strerror(errno);
 414+ return false;
 415+ }
 416+
 417+ pf << getpid() << '\n';
 418+ atexit(rmpidfile);
 419+ signal(SIGINT, do_signal);
 420+ signal(SIGTERM, do_signal);
 421+ return true;
 422+}
 423+
223424 int
224425 main(int argc, char **argv)
225426 {
226 - int delay = 10, pagesize = sysconf(_SC_PAGE_SIZE);
227 - std::size_t limit = 0, thresh = 0;
 427+ int pagesize = sysconf(_SC_PAGE_SIZE), fflag = 0;
228428 int c;
229 - std::set<uid_t> exempt;
230429
 430+ config.exempt.insert(0); /* root is always exempt */
 431+
231432 char nodename[255];
232433 gethostname(nodename, sizeof nodename);
233434
234 - while ((c = getopt(argc, argv, "l:t:e:vh")) != -1) {
 435+ while ((c = getopt(argc, argv, "fvhc:")) != -1) {
235436 switch (c) {
236 - case 'l':
237 - try {
238 - limit = boost::lexical_cast<std::size_t>(optarg) * 1024 * 1024;
239 - } catch (boost::bad_lexical_cast &) {
240 - std::cerr << boost::format("\"%s\" is not a valid number\n") % optarg;
241 - return 1;
242 - }
 437+ case 'f':
 438+ fflag++;
243439 break;
244440
245 - case 't':
246 - try {
247 - thresh = boost::lexical_cast<std::size_t>(optarg) * 1024 * 1024;
248 - } catch (boost::bad_lexical_cast &) {
249 - std::cerr << boost::format("\"%s\" is not a valid number\n") % optarg;
250 - return 1;
251 - }
 441+ case 'c':
 442+ CONFFILE = optarg;
252443 break;
253444
254 - case 'd':
255 - try {
256 - delay = boost::lexical_cast<std::size_t>(optarg);
257 - } catch (boost::bad_lexical_cast &) {
258 - std::cerr << boost::format("\"%s\" is not a valid number\n") % optarg;
259 - return 1;
260 - }
261 - break;
262 -
263 - case 'e':
264 - uid_t u;
265 - if ((u = uid(optarg)) == -1) {
266 - std::cerr << boost::format("user \"%s\" does not exist\n") % optarg;
267 - return 1;
268 - }
269 - exempt.insert(u);
270 - break;
271 -
272445 case 'v':
273446 version();
274447 return 0;
@@ -286,23 +459,29 @@
287460 argc -= optind;
288461 argv += optind;
289462
290 - if (limit == 0 || thresh == 0) {
291 - usage();
 463+ openlog("slayerd", LOG_PID, LOG_DAEMON);
 464+
 465+ if (!configure())
292466 return 1;
 467+
 468+ if (config.limit == 0 || config.thresh == 0) {
 469+ std::cerr << "invalid limit/threshold\n";
 470+ return 1;
293471 }
294472
295 - openlog("slayerd", LOG_PID, LOG_DAEMON);
296 -
297 - if (daemon(0, 0) == -1) {
 473+ if (!fflag && daemon(0, 0) == -1) {
298474 std::cerr << boost::format("cannot daemonise: %s\n") % std::strerror(errno);
299475 return 1;
300476 }
301477
 478+ if (!do_pidfile())
 479+ return 1;
 480+
302481 if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1)
303482 log(str(boost::format("warning: cannot lock memory: %s\n") % std::strerror(errno)));
304483
305484 log(str(boost::format("delay: %d, limit: %dM, threshold: %dM\n")
306 - % delay % (limit / 1024 / 1024) % (thresh / 1024 / 1024)));
 485+ % config.delay % (config.limit / 1024 / 1024) % (config.thresh / 1024 / 1024)));
307486
308487 for (;;) {
309488 fs::path proc(PATH_PROC);
@@ -345,41 +524,23 @@
346525 user &u = users[i];
347526 std::size_t bytes = u.rss * pagesize;
348527
349 - if (exempt.find(u.uid) != exempt.end())
 528+ if (config.exempt.find(u.uid) != config.exempt.end())
350529 continue;
351530
352 - if (bytes < limit)
 531+ if (bytes < config.limit)
353532 continue;
354533
355534 std::string uname = username(u.uid);
356 - std::string message = str(boost::format(
357 -"From: slayerd <slayerd@%1%>\n"
358 -"To: %2% <%2%@%1%>\n"
359 -"Subject: Excessive memory usage from your processes.\n"
360 -"Reply-To: Wikimedia Toolserver Administrators <ts-admins@wikimedia.org>\n"
361 -"X-Mailer: slayerd $Revision$\n"
362 -"\n"
363 -"This message was automatically generated by slayerd on %1%.\n"
364 -"\n"
365 -"Hello,\n"
366 -"\n"
367 -"One or more of your processes on the host %1%\n"
368 -"were exceeding the configured memory limit, which is %3% megabytes.\n"
369 -"I have killed enough of your processes to bring your usage back to the\n"
370 -"threshold limit, which is %4% megabytes.\n"
371 -"\n"
372 -"These are the processes I killed:\n"
373 -"\n"
374 - ) % nodename % uname % (limit / 1024 / 1024) % (thresh / 1024 / 1024));
 535+ std::string process_list;
375536
376537 log(str(boost::format("user \"%s\" is using %dM, over configured limit %dM")
377538 % uname
378539 % (bytes / 1024 / 1024)
379 - % (limit / 1024 / 1024)));
 540+ % (config.limit / 1024 / 1024)));
380541
381542 std::sort(u.processes.begin(), u.processes.end(), field_comparator<process, long, &process::_rss>);
382543
383 - while (bytes >= thresh && !u.processes.empty()) {
 544+ while (bytes >= config.thresh && !u.processes.empty()) {
384545 process &p = u.processes[0];
385546 std::string comm = p._comm.substr(1);
386547 comm.resize(comm.size() - 1);
@@ -391,7 +552,7 @@
392553 % (p._rss * pagesize / 1024 / 1024)
393554 % ((bytes - p._rss * pagesize) / 1024 / 1024)));
394555
395 - message += str(boost::format(" %s (pid %d), using %d megabyte(s)\n")
 556+ process_list += str(boost::format(" %s (pid %d), using %d megabyte(s)\n")
396557 % comm % p._pid % (p._rss * pagesize / 1024 / 1024));
397558
398559 bytes -= p._rss * pagesize;
@@ -401,21 +562,19 @@
402563 log(str(boost::format(" usage is now within acceptable limits (%dM)")
403564 % (bytes / 1024 / 1024)));
404565
405 - message += str(boost::format(
406 -"\n"
407 -"Your total memory usage is now %d megabyte(s).\n"
408 -"\n"
409 -"Excessive memory usage is usually a symptom of a broken program. Please\n"
410 -"investigate the cause of the problem and fix it before you restart these\n"
411 -"processes.\n"
412 -"\n"
413 -"Regards,\n"
414 -" slayerd (the process slayer)\n"
415 - ) % (bytes / 1024 / 1024));
 566+ std::map<std::string, std::string> msgvars;
 567+ msgvars["limit"] = boost::lexical_cast<std::string>(config.limit / 1024 / 1024);
 568+ msgvars["thresh"] = boost::lexical_cast<std::string>(config.thresh / 1024 / 1024);
 569+ msgvars["user"] = uname;
 570+ msgvars["hostname"] = nodename;
 571+ msgvars["current"] = boost::lexical_cast<std::string>(bytes / 1024 / 1024);
 572+ msgvars["processes"] = process_list;
416573
417 - sendmail(uname, message);
 574+ std::string message = replace_file(config.mailmessage, msgvars);
 575+ if (!message.empty())
 576+ sendmail(uname, message);
418577 }
419578
420 - sleep(delay);
 579+ sleep(config.delay);
421580 }
422581 }
Property changes on: trunk/tools/slayerd/slayerd.cc
___________________________________________________________________
Added: svn:keywords
423582 + Id Revision
Index: trunk/tools/slayerd/Makefile
@@ -1,5 +1,11 @@
 2+PREFIX ?= /usr/local
 3+CONFDIR ?= /etc/slayerd
 4+SBINDIR ?= $(PREFIX)/sbin
 5+MANDIR ?= $(PREFIX)/share/man/man8
 6+
27 CXX = g++
38 CXXFLAGS = -O2 -g3 -ggdb
 9+CPPFLAGS = -DETCDIR=\"$(CONFDIR)\" -DPREFIX=\"$(PREFIX)\"
410 LDFLAGS =
511 SRCS = slayerd.cc
612 OBJS = $(SRCS:.cc=.o)
@@ -8,9 +14,19 @@
915 $(CXX) $(CXXFLAGS) $(LDFLAGS) $^ -o $@ -lboost_filesystem
1016
1117 install: slayerd
12 - install -c -s -o root -g root -m 755 slayerd /usr/local/sbin
 18+ install -d $(DESTDIR)$(SBINDIR)
 19+ install -d $(DESTDIR)$(CONFDIR)
 20+ install -d $(DESTDIR)$(MANDIR)
 21+ install -c -s -o root -g root -m 755 slayerd $(DESTDIR)$(SBINDIR)
 22+ install -c -o root -g root -m 640 slayerd.conf.example $(DESTDIR)$(CONFDIR)
 23+ install -c -o root -g root -m 640 mailmessage $(DESTDIR)$(CONFDIR)
 24+ install -c -o root -g root -m 644 slayerd.8 $(DESTDIR)$(MANDIR)
1325
1426 .cc.o:
1527 $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $<
1628
 29+clean:
 30+ rm -f slayerd slayerd.o
 31+
 32+.PHONY: clean install
1733 .SUFFICES: .cc .o
Property changes on: trunk/tools/slayerd/Makefile
___________________________________________________________________
Added: svn:keywords
1834 + Id Revision