Index: trunk/tools/slayerd/Makefile |
— | — | @@ -7,13 +7,13 @@ |
8 | 8 | |
9 | 9 | CXX = g++ |
10 | 10 | CXXFLAGS = -O2 -g3 -ggdb |
11 | | -CPPFLAGS = -DETCDIR=\"$(CONFDIR)\" -DPREFIX=\"$(PREFIX)\" |
12 | | -LDFLAGS = |
13 | | -SRCS = slayerd.cc |
| 11 | +CPPFLAGS = -DETCDIR=\"$(CONFDIR)\" -DPREFIX=\"$(PREFIX)\" -I/usr/local/include |
| 12 | +LDFLAGS = -L/usr/local/lib |
| 13 | +SRCS = slayerd.cc process.cc |
14 | 14 | OBJS = $(SRCS:.cc=.o) |
15 | 15 | |
16 | 16 | slayerd: $(OBJS) |
17 | | - $(CXX) $(CXXFLAGS) $(LDFLAGS) $^ -o $@ -lboost_filesystem |
| 17 | + $(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) -o $@ -lboost_filesystem |
18 | 18 | |
19 | 19 | install: slayerd |
20 | 20 | install -d $(DESTDIR)$(SBINDIR) |
Index: trunk/tools/slayerd/debian/files |
— | — | @@ -1,2 +1,3 @@ |
2 | 2 | slayerd_1.5_amd64.deb admin extra |
3 | 3 | slayerd_1.6_amd64.deb admin extra |
| 4 | +slayerd_1.6_amd64.deb admin extra |
Index: trunk/tools/slayerd/process.cc |
— | — | @@ -0,0 +1,13 @@ |
| 2 | +/* Copyright (c) 2007-2009 River Tarnell <river@loreley.flyingparchment.org.uk>. */ |
| 3 | +/* |
| 4 | + * Permission is granted to anyone to use this software for any purpose, |
| 5 | + * including commercial applications, and to alter it and redistribute it |
| 6 | + * freely. This software is provided 'as-is', without any express or implied |
| 7 | + * warranty. |
| 8 | + */ |
| 9 | + |
| 10 | +#ifdef __linux__ |
| 11 | +# include "proc_linux.cc" |
| 12 | +#else |
| 13 | +# error dont know how to enumerate processes on this platform |
| 14 | +#endif |
Index: trunk/tools/slayerd/process.h |
— | — | @@ -0,0 +1,31 @@ |
| 2 | +/* Copyright (c) 2007-2009 River Tarnell <river@loreley.flyingparchment.org.uk>. */ |
| 3 | +/* |
| 4 | + * Permission is granted to anyone to use this software for any purpose, |
| 5 | + * including commercial applications, and to alter it and redistribute it |
| 6 | + * freely. This software is provided 'as-is', without any express or implied |
| 7 | + * warranty. |
| 8 | + */ |
| 9 | + |
| 10 | +/* $Id$ */ |
| 11 | + |
| 12 | +#ifndef PROCESS_H |
| 13 | +#define PROCESS_H |
| 14 | + |
| 15 | +#include <vector> |
| 16 | + |
| 17 | +struct process { |
| 18 | + typedef boost::shared_ptr<process> pointer; |
| 19 | + |
| 20 | + virtual ~process() {}; |
| 21 | + |
| 22 | + virtual pid_t pid() const = 0; |
| 23 | + virtual std::string command() const = 0; |
| 24 | + virtual std::string cmdline() const = 0; |
| 25 | + virtual std::size_t rss() const = 0; |
| 26 | + virtual std::size_t vsize() const = 0; |
| 27 | + virtual uid_t uid() const = 0; |
| 28 | +}; |
| 29 | + |
| 30 | +std::vector<process::pointer> enumerate_processes(); |
| 31 | + |
| 32 | +#endif /* !PROCESS_H */ |
Index: trunk/tools/slayerd/proc_linux.cc |
— | — | @@ -0,0 +1,151 @@ |
| 2 | +/* Copyright (c) 2007-2009 River Tarnell <river@loreley.flyingparchment.org.uk>. */ |
| 3 | +/* |
| 4 | + * Permission is granted to anyone to use this software for any purpose, |
| 5 | + * including commercial applications, and to alter it and redistribute it |
| 6 | + * freely. This software is provided 'as-is', without any express or implied |
| 7 | + * warranty. |
| 8 | + */ |
| 9 | + |
| 10 | +/* $Id$ */ |
| 11 | + |
| 12 | +#include <sys/stat.h> |
| 13 | +#include <unistd.h> |
| 14 | + |
| 15 | +#include <string> |
| 16 | +#include <fstream> |
| 17 | +#include <boost/shared_ptr.hpp> |
| 18 | +#include <boost/filesystem.hpp> |
| 19 | +#include <boost/lexical_cast.hpp> |
| 20 | + |
| 21 | +#include "process.h" |
| 22 | + |
| 23 | +namespace fs = boost::filesystem; |
| 24 | + |
| 25 | +namespace { |
| 26 | + std::string PATH_PROC = "/proc"; |
| 27 | +} |
| 28 | + |
| 29 | +struct process_linux : process { |
| 30 | + process_linux(fs::path const &pth); |
| 31 | + |
| 32 | + pid_t pid() const { return _pid; } |
| 33 | + std::string command() const { return _comm; } |
| 34 | + std::string cmdline() const { return _fullcomm; } |
| 35 | + std::size_t rss() const { return _mres; } |
| 36 | + std::size_t vsize() const { return _vsize; } |
| 37 | + uid_t uid() const { return _uid; } |
| 38 | + |
| 39 | + pid_t _pid; |
| 40 | + /* short command from /proc/{pid}/stat */ |
| 41 | + std::string _comm; |
| 42 | + /* fulll command from /proc/{pid}/cmdline */ |
| 43 | + std::string _fullcomm; |
| 44 | + unsigned long _vsize; |
| 45 | + long _rss; |
| 46 | + uid_t _uid; |
| 47 | + int _mres; |
| 48 | + |
| 49 | + void _read_proc_data(fs::path const &); |
| 50 | +}; |
| 51 | + |
| 52 | +process_linux::process_linux(fs::path const &pth) |
| 53 | + : _pid(boost::lexical_cast<pid_t>(pth.leaf())) |
| 54 | +{ |
| 55 | + struct stat st; |
| 56 | + if (::stat(pth.native_directory_string().c_str(), &st) == -1) |
| 57 | + throw std::runtime_error("could not stat proc dir"); |
| 58 | + _uid = st.st_uid; |
| 59 | + |
| 60 | + _read_proc_data(pth); |
| 61 | +} |
| 62 | + |
| 63 | +void |
| 64 | +process_linux::_read_proc_data(fs::path const &pth) |
| 65 | +{ |
| 66 | + /* Everything that we can collect, but that doesn't belong in process. */ |
| 67 | + unsigned long _flags, _minflt, _cminflt, _majflt, _cmajflt, _utime, _stime; |
| 68 | + long _cutime, _cstime, _priority, _itrealvalue, _starttime; |
| 69 | + unsigned long _rlim, _startcode, _endcode, _stackstart, _kstkesp, _kstkeip; |
| 70 | + unsigned long _signal, _blocked, _sigignore, _sigcatch, _wchan, _nswap, _cnswap; |
| 71 | + int _exit_signal, _processor; |
| 72 | + unsigned long _rt_priority, _policy; |
| 73 | + int _mshare, _mtext, _mlib, _mdata; |
| 74 | + pid_t _ppid, _pgrp, _sid, _tty, _tpgid, _state, _msize, _nice; |
| 75 | + |
| 76 | + { |
| 77 | + std::ifstream f((pth / "stat").native_file_string().c_str()); |
| 78 | + |
| 79 | + if (!f) |
| 80 | + throw std::runtime_error("could not read line from stat"); |
| 81 | + |
| 82 | + long dummy; |
| 83 | + if (!(f >> _pid >> _comm >> _state >> _ppid >> _pgrp >> _sid >> _tty >> _tpgid |
| 84 | + >> _flags >> _minflt >> _cminflt >> _majflt >> _cmajflt >> _utime |
| 85 | + >> _stime >> _cutime >> _cstime >> _priority >> _nice >> dummy >> _itrealvalue |
| 86 | + >> _starttime >> _vsize >> _rss >> _rlim >> _startcode >> _endcode |
| 87 | + >> _stackstart >> _kstkesp >> _kstkeip >> _signal >> _blocked >> _sigignore |
| 88 | + >> _sigcatch >> _wchan >> _nswap >> _cnswap >> _exit_signal >> _processor |
| 89 | + >> _rt_priority >> _policy |
| 90 | + )) |
| 91 | + throw std::runtime_error("could not parse stat line"); |
| 92 | + } |
| 93 | + |
| 94 | + { |
| 95 | + std::ifstream f((pth / "statm").native_file_string().c_str()); |
| 96 | + |
| 97 | + if (!f) |
| 98 | + throw std::runtime_error("could not read line from stat"); |
| 99 | + |
| 100 | + if (!(f >> _msize >> _mres >> _mshare >> _mtext >> _mlib >> _mdata)) |
| 101 | + throw std::runtime_error("could not parse statm line"); |
| 102 | + } |
| 103 | + |
| 104 | + { |
| 105 | + std::ifstream f((pth / "cmdline").native_file_string().c_str()); |
| 106 | + |
| 107 | + if (!f) |
| 108 | + throw std::runtime_error("could not read line from cmdline"); |
| 109 | + |
| 110 | + if (!std::getline(f, _fullcomm)) |
| 111 | + throw std::runtime_error("could not parse cmdline"); |
| 112 | + } |
| 113 | +} |
| 114 | + |
| 115 | +template<typename C> |
| 116 | +struct directory_enumerator { |
| 117 | + C &list; |
| 118 | + |
| 119 | + directory_enumerator(C &list) : list(list) {} |
| 120 | + |
| 121 | + void operator() (fs::path const &pth) const { |
| 122 | + /* |
| 123 | + * Ensure it is actually a pid. |
| 124 | + */ |
| 125 | + try { |
| 126 | + boost::lexical_cast<pid_t>(pth.leaf()); |
| 127 | + } catch (boost::bad_lexical_cast const &) { |
| 128 | + return; |
| 129 | + } |
| 130 | + |
| 131 | + try { |
| 132 | + list.push_back(process::pointer(new process_linux(pth))); |
| 133 | + } catch (...) {} |
| 134 | + } |
| 135 | +}; |
| 136 | + |
| 137 | +template<typename C> |
| 138 | +directory_enumerator<C> |
| 139 | +enumerate_directory(C &list) { |
| 140 | + return directory_enumerator<C>(list); |
| 141 | +} |
| 142 | + |
| 143 | +std::vector<process::pointer> |
| 144 | +enumerate_processes() |
| 145 | +{ |
| 146 | + std::vector<process::pointer> processes; |
| 147 | + fs::path proc(PATH_PROC); |
| 148 | + |
| 149 | + std::for_each(fs::directory_iterator(proc), fs::directory_iterator(), |
| 150 | + enumerate_directory(processes)); |
| 151 | + return processes; |
| 152 | +} |
Index: trunk/tools/slayerd/slayerd.cc |
— | — | @@ -1,4 +1,4 @@ |
2 | | -/* Copyright (c) 2007 River Tarnell <river@attenuate.org>. */ |
| 2 | +/* Copyright (c) 2007-2009 River Tarnell <river@loreley.flyingparchment.org.uk>. */ |
3 | 3 | /* |
4 | 4 | * Permission is granted to anyone to use this software for any purpose, |
5 | 5 | * including commercial applications, and to alter it and redistribute it |
— | — | @@ -12,35 +12,37 @@ |
13 | 13 | * slayerd: monitor user activity and regulate users using too much RAM. |
14 | 14 | */ |
15 | 15 | |
16 | | -#include <string> |
17 | | -#include <iostream> |
18 | | -#include <fstream> |
19 | | -#include <algorithm> |
20 | | -#include <stdexcept> |
21 | | -#include <vector> |
22 | | -#include <map> |
23 | | -#include <set> |
24 | | -#include <cerrno> |
25 | | -#include <cstring> |
| 16 | +#include <string> |
| 17 | +#include <iostream> |
| 18 | +#include <fstream> |
| 19 | +#include <algorithm> |
| 20 | +#include <stdexcept> |
| 21 | +#include <vector> |
| 22 | +#include <map> |
| 23 | +#include <set> |
| 24 | +#include <cerrno> |
| 25 | +#include <cstring> |
26 | 26 | |
27 | | -#include <sys/types.h> |
28 | | -#include <sys/mman.h> |
29 | | -#include <sys/stat.h> |
30 | | -#include <sys/wait.h> |
31 | | -#include <unistd.h> |
32 | | -#include <pwd.h> |
33 | | -#include <signal.h> |
34 | | -#include <syslog.h> |
| 27 | +#include <sys/types.h> |
| 28 | +#include <sys/mman.h> |
| 29 | +#include <sys/stat.h> |
| 30 | +#include <sys/wait.h> |
| 31 | +#include <unistd.h> |
| 32 | +#include <pwd.h> |
| 33 | +#include <signal.h> |
| 34 | +#include <syslog.h> |
35 | 35 | |
36 | | -#include <boost/filesystem/path.hpp> |
37 | | -#include <boost/filesystem/operations.hpp> |
38 | | -#include <boost/lexical_cast.hpp> |
39 | | -#include <boost/format.hpp> |
| 36 | +#include <boost/filesystem/path.hpp> |
| 37 | +#include <boost/filesystem/operations.hpp> |
| 38 | +#include <boost/lexical_cast.hpp> |
| 39 | +#include <boost/format.hpp> |
| 40 | +#include <boost/shared_ptr.hpp> |
40 | 41 | |
| 42 | +#include "process.h" |
| 43 | + |
41 | 44 | namespace fs = boost::filesystem; |
42 | 45 | |
43 | 46 | namespace { |
44 | | - std::string PATH_PROC = "/proc"; |
45 | 47 | std::string CONFFILE = "/etc/slayerd/slayerd.conf"; |
46 | 48 | } |
47 | 49 | |
— | — | @@ -67,116 +69,6 @@ |
68 | 70 | {} |
69 | 71 | } config; |
70 | 72 | |
71 | | -struct process { |
72 | | - process(fs::path const &pth); |
73 | | - |
74 | | - pid_t _pid; |
75 | | - /* short command from /proc/{pid}/stat */ |
76 | | - std::string _comm; |
77 | | - /* fulll command from /proc/{pid}/cmdline */ |
78 | | - std::string _fullcomm; |
79 | | - char _state; |
80 | | - pid_t _ppid; |
81 | | - pid_t _pgrp; |
82 | | - pid_t _sid; |
83 | | - int _tty; |
84 | | - pid_t _tpgid; |
85 | | - unsigned long _flags; |
86 | | - unsigned long _minflt; |
87 | | - unsigned long _cminflt; |
88 | | - unsigned long _majflt; |
89 | | - unsigned long _cmajflt; |
90 | | - unsigned long _utime; |
91 | | - unsigned long _stime; |
92 | | - long _cutime; |
93 | | - long _cstime; |
94 | | - long _priority; |
95 | | - long _itrealvalue; |
96 | | - long _starttime; |
97 | | - unsigned long _vsize; |
98 | | - long _rss; |
99 | | - unsigned long _rlim; |
100 | | - unsigned long _startcode; |
101 | | - unsigned long _endcode; |
102 | | - unsigned long _stackstart; |
103 | | - unsigned long _kstkesp; |
104 | | - unsigned long _kstkeip; |
105 | | - unsigned long _signal; |
106 | | - unsigned long _blocked; |
107 | | - unsigned long _sigignore; |
108 | | - unsigned long _sigcatch; |
109 | | - unsigned long _wchan; |
110 | | - unsigned long _nswap; |
111 | | - unsigned long _cnswap; |
112 | | - int _exit_signal; |
113 | | - int _processor; |
114 | | - unsigned long _rt_priority; |
115 | | - unsigned long _policy; |
116 | | - long _nice; |
117 | | - uid_t _uid; |
118 | | - int _msize; |
119 | | - int _mres; |
120 | | - int _mshare; |
121 | | - int _mtext; |
122 | | - int _mlib; |
123 | | - int _mdata; |
124 | | - |
125 | | - void _read_proc_data(fs::path const &); |
126 | | -}; |
127 | | - |
128 | | -process::process(fs::path const &pth) |
129 | | - : _pid(boost::lexical_cast<pid_t>(pth.leaf())) |
130 | | -{ |
131 | | - struct stat st; |
132 | | - if (::stat(pth.native_directory_string().c_str(), &st) == -1) |
133 | | - throw std::runtime_error("could not stat proc dir"); |
134 | | - _uid = st.st_uid; |
135 | | - |
136 | | - _read_proc_data(pth); |
137 | | -} |
138 | | - |
139 | | -void |
140 | | -process::_read_proc_data(fs::path const &pth) |
141 | | -{ |
142 | | - { |
143 | | - std::ifstream f((pth / "stat").native_file_string().c_str()); |
144 | | - |
145 | | - if (!f) |
146 | | - throw std::runtime_error("could not read line from stat"); |
147 | | - |
148 | | - long dummy; |
149 | | - if (!(f >> _pid >> _comm >> _state >> _ppid >> _pgrp >> _sid >> _tty >> _tpgid |
150 | | - >> _flags >> _minflt >> _cminflt >> _majflt >> _cmajflt >> _utime |
151 | | - >> _stime >> _cutime >> _cstime >> _priority >> _nice >> dummy >> _itrealvalue |
152 | | - >> _starttime >> _vsize >> _rss >> _rlim >> _startcode >> _endcode |
153 | | - >> _stackstart >> _kstkesp >> _kstkeip >> _signal >> _blocked >> _sigignore |
154 | | - >> _sigcatch >> _wchan >> _nswap >> _cnswap >> _exit_signal >> _processor |
155 | | - >> _rt_priority >> _policy |
156 | | - )) |
157 | | - throw std::runtime_error("could not parse stat line"); |
158 | | - } |
159 | | - |
160 | | - { |
161 | | - std::ifstream f((pth / "statm").native_file_string().c_str()); |
162 | | - |
163 | | - if (!f) |
164 | | - throw std::runtime_error("could not read line from stat"); |
165 | | - |
166 | | - if (!(f >> _msize >> _mres >> _mshare >> _mtext >> _mlib >> _mdata)) |
167 | | - throw std::runtime_error("could not parse statm line"); |
168 | | - } |
169 | | - |
170 | | - { |
171 | | - std::ifstream f((pth / "cmdline").native_file_string().c_str()); |
172 | | - |
173 | | - if (!f) |
174 | | - throw std::runtime_error("could not read line from cmdline"); |
175 | | - |
176 | | - if (!std::getline(f, _fullcomm)) |
177 | | - throw std::runtime_error("could not parse cmdline"); |
178 | | - } |
179 | | -} |
180 | | - |
181 | 73 | std::string |
182 | 74 | username(uid_t uid) |
183 | 75 | { |
— | — | @@ -195,40 +87,12 @@ |
196 | 88 | return p->pw_uid; |
197 | 89 | } |
198 | 90 | |
199 | | -template<typename C> |
200 | | -struct directory_enumerator { |
201 | | - C &list; |
202 | | - |
203 | | - directory_enumerator(C &list) : list(list) {} |
204 | | - |
205 | | - void operator() (fs::path const &pth) const { |
206 | | - /* |
207 | | - * Ensure it is actually a pid. |
208 | | - */ |
209 | | - try { |
210 | | - boost::lexical_cast<pid_t>(pth.leaf()); |
211 | | - } catch (boost::bad_lexical_cast const &) { |
212 | | - return; |
213 | | - } |
214 | | - |
215 | | - try { |
216 | | - list.push_back(process(pth)); |
217 | | - } catch (...) {} |
218 | | - } |
219 | | -}; |
220 | | - |
221 | | -template<typename C> |
222 | | -directory_enumerator<C> |
223 | | -enumerate_directory(C &list) { |
224 | | - return directory_enumerator<C>(list); |
225 | | -} |
226 | | - |
227 | 91 | struct user { |
228 | 92 | user() : uid(-1), rss(0) {} |
229 | 93 | |
230 | 94 | uid_t uid; |
231 | | - unsigned long rss; |
232 | | - std::vector<process> processes; |
| 95 | + std::size_t rss; |
| 96 | + std::vector<process::pointer> processes; |
233 | 97 | }; |
234 | 98 | |
235 | 99 | /* |
— | — | @@ -241,6 +105,13 @@ |
242 | 106 | return b.*F < a.*F; |
243 | 107 | } |
244 | 108 | |
| 109 | +template<typename S, typename T, T (S::*F)(void) const> |
| 110 | +bool |
| 111 | +ptmf_comparator(boost::shared_ptr<S> const &a, boost::shared_ptr<S> const &b) |
| 112 | +{ |
| 113 | + return ((*b).*F)() < ((*a).*F)(); |
| 114 | +} |
| 115 | + |
245 | 116 | void |
246 | 117 | version(void) { |
247 | 118 | std::cerr << "slayerd " << VERSION << "\n"; |
— | — | @@ -580,22 +451,18 @@ |
581 | 452 | % config.delay % (config.limit / 1024 / 1024) % (config.thresh / 1024 / 1024))); |
582 | 453 | |
583 | 454 | for (;;) { |
584 | | - fs::path proc(PATH_PROC); |
585 | | - std::vector<process> processes; |
| 455 | + std::vector<process::pointer> processes(enumerate_processes()); |
586 | 456 | |
587 | | - std::for_each(fs::directory_iterator(proc), fs::directory_iterator(), |
588 | | - enumerate_directory(processes)); |
589 | | - |
590 | 457 | /* |
591 | 458 | * Aggregate the processes by user. |
592 | 459 | */ |
593 | 460 | std::vector<user> users; |
594 | 461 | for (std::size_t i = 0, end = processes.size(); i < end; ++i) { |
595 | | - process &p = processes[i]; |
| 462 | + process::pointer p = processes[i]; |
596 | 463 | user *u = 0; |
597 | 464 | |
598 | 465 | for (std::size_t ui = 0, uend = users.size(); ui != uend; ++ui) |
599 | | - if (users[ui].uid == p._uid) { |
| 466 | + if (users[ui].uid == p->uid()) { |
600 | 467 | u = &users[ui]; |
601 | 468 | break; |
602 | 469 | } |
— | — | @@ -603,18 +470,18 @@ |
604 | 471 | if (u == 0) { |
605 | 472 | std::size_t n = users.size(); |
606 | 473 | users.resize(n + 1); |
607 | | - users[n].uid = p._uid; |
| 474 | + users[n].uid = p->uid(); |
608 | 475 | u = &users[n]; |
609 | 476 | } |
610 | 477 | |
611 | | - u->rss += p._mres; |
| 478 | + u->rss += p->rss(); |
612 | 479 | u->processes.push_back(p); |
613 | 480 | } |
614 | 481 | |
615 | 482 | /* |
616 | 483 | * Sort user by RSS. |
617 | 484 | */ |
618 | | - std::sort(users.begin(), users.end(), field_comparator<user, unsigned long, &user::rss>); |
| 485 | + std::sort(users.begin(), users.end(), field_comparator<user, std::size_t, &user::rss>); |
619 | 486 | |
620 | 487 | for (std::size_t i = 0, end = users.size(); i < end; ++i) { |
621 | 488 | user &u = users[i]; |
— | — | @@ -637,31 +504,32 @@ |
638 | 505 | % (bytes / 1024 / 1024) |
639 | 506 | % (config.limit / 1024 / 1024))); |
640 | 507 | |
641 | | - std::sort(u.processes.begin(), u.processes.end(), field_comparator<process, int, &process::_mres>); |
| 508 | + std::sort(u.processes.begin(), u.processes.end(), ptmf_comparator<process, std::size_t, &process::rss>); |
642 | 509 | |
643 | 510 | while (bytes >= config.thresh && !u.processes.empty()) { |
644 | | - process &p = u.processes[0]; |
| 511 | + process::pointer p = u.processes[0]; |
645 | 512 | |
646 | 513 | /* command is (%s) formatted, strip parentheses. */ |
647 | | - std::string comm = p._comm.substr(1); |
| 514 | + std::string comm = p->command().substr(1); |
648 | 515 | comm.resize(comm.size() - 1); |
649 | 516 | |
650 | 517 | /* arguments are \0 separated, use spaces for display */ |
651 | | - std::replace(p._fullcomm.begin(), p._fullcomm.end(), '\0', ' '); |
| 518 | + std::string cm = p->cmdline(); |
| 519 | + std::replace(cm.begin(), cm.end(), '\0', ' '); |
652 | 520 | |
653 | 521 | if (!config.debug) |
654 | | - kill(p._pid, SIGKILL); |
| 522 | + kill(p->pid(), SIGKILL); |
655 | 523 | |
656 | | - std::size_t thissize = std::size_t(p._mres) * pagesize; |
| 524 | + std::size_t thissize = std::size_t(p->rss()) * pagesize; |
657 | 525 | |
658 | 526 | log(str(boost::format(" killed process \"%s\" (pid %d) using %dM, usage now %dM") |
659 | | - % comm % p._pid |
| 527 | + % comm % p->pid() |
660 | 528 | % (thissize / 1024 / 1024) |
661 | 529 | % ((bytes - thissize) / 1024 / 1024))); |
662 | 530 | |
663 | 531 | process_list += str(boost::format(" %s (pid %d), using %d megabyte(s).\n" |
664 | | - " command: \"%s\"\n") |
665 | | - % comm % p._pid % (thissize / 1024 / 1024) % p._fullcomm); |
| 532 | + " command: %s\n") |
| 533 | + % comm % p->pid() % (thissize / 1024 / 1024) % p->cmdline()); |
666 | 534 | |
667 | 535 | bytes -= thissize; |
668 | 536 | u.processes.erase(u.processes.begin()); |