@cryptotaxi247 / netdata-1 / commits / 221e7221d

properly set negative out-of-memory (OOM) scores; #2549

Costa Tsaousis (ktsaou) committed Aug 22, 2017 at 22:01 UTC 221e7221ddc2fd68f5e15c3abb676b3791367904
3 files changed +85 -21
src/daemon.c
+49 -13
@@ -167,34 +167,70 @@ int become_user(const char *username, int pid_fd) {
167 #endif
168
169 static void oom_score_adj(void) {
170 - char buf[10 + 1];
171 - snprintfz(buf, 10, "%d", OOM_SCORE_ADJ_MAX);
170 + char buf[30 + 1];
171 + long long int old_score, wanted_score = OOM_SCORE_ADJ_MAX, final_score = 0;
172 +
173 + // read the existing score
174 + if(read_single_signed_number_file("/proc/self/oom_score_adj", &old_score)) {
175 + error("Out-Of-Memory (OOM) score setting is not supported on this system.");
176 + return;
177 + }
178 +
179 + if(old_score != 0)
180 + wanted_score = old_score;
181
182 // check the environment
183 char *s = getenv("OOMScoreAdjust");
175 - if(!s || !*s) s = buf;
184 + if(!s || !*s) {
185 + snprintfz(buf, 30, "%d", (int)wanted_score);
186 + s = buf;
187 + }
188
189 // check netdata.conf configuration
190 s = config_get(CONFIG_SECTION_GLOBAL, "OOM score", s);
179 - if(!s || !*s) s = buf;
191 + if(s && *s && (isdigit(*s) || *s == '-' || *s == '+'))
192 + wanted_score = atoll(s);
193 + else {
194 + info("Out-Of-Memory (OOM) score not changed due to non-numeric setting: '%s' (running with %d)", s, (int)old_score);
195 + return;
196 + }
197
181 - if(!isdigit(*s) && *s != '-' && *s != '+') {
182 - info("Out-Of-Memory score not changed due to setting: '%s'", s);
198 + if(wanted_score < OOM_SCORE_ADJ_MIN) {
199 + error("Wanted Out-Of-Memory (OOM) score %d is too small. Using %d", (int)wanted_score, (int)OOM_SCORE_ADJ_MIN);
200 + wanted_score = OOM_SCORE_ADJ_MIN;
201 + }
202 +
203 + if(wanted_score > OOM_SCORE_ADJ_MAX) {
204 + error("Wanted Out-Of-Memory (OOM) score %d is too big. Using %d", (int)wanted_score, (int)OOM_SCORE_ADJ_MAX);
205 + wanted_score = OOM_SCORE_ADJ_MAX;
206 + }
207 +
208 + if(old_score == wanted_score) {
209 + info("Out-Of-Memory (OOM) score is already set to the wanted value %d", (int)old_score);
210 return;
211 }
212
186 - int done = 0;
213 + int written = 0;
214 int fd = open("/proc/self/oom_score_adj", O_WRONLY);
215 if(fd != -1) {
189 - ssize_t len = strlen(s);
190 - if(len > 0 && write(fd, buf, (size_t)len) == len) done = 1;
216 + snprintfz(buf, 30, "%d", (int)wanted_score);
217 + ssize_t len = strlen(buf);
218 + if(len > 0 && write(fd, buf, (size_t)len) == len) written = 1;
219 close(fd);
192 - }
220
194 - if(!done)
195 - error("Cannot adjust my Out-Of-Memory score to '%s'.", s);
221 + if(written) {
222 + if(read_single_signed_number_file("/proc/self/oom_score_adj", &final_score))
223 + error("Adjusted my Out-Of-Memory (OOM) score to %d, but cannot verify it.", (int)wanted_score);
224 + else if(final_score == wanted_score)
225 + info("Adjusted my Out-Of-Memory (OOM) score from %d to %d.", (int)old_score, (int)final_score);
226 + else
227 + error("Adjusted my Out-Of-Memory (OOM) score from %d to %d, but it has been set to %d.", (int)old_score, (int)wanted_score, (int)final_score);
228 + }
229 + else
230 + error("Failed to adjust my Out-Of-Memory (OOM) score to %d. Running with %d. (systemd systems may change it via netdata.service)", (int)wanted_score, (int)old_score);
231 + }
232 else
197 - info("Adjusted my Out-Of-Memory score to '%s'.", s);
233 + error("Failed to adjust my Out-Of-Memory (OOM) score. Cannot open /proc/self/oom_score_adj for writing.");
234 }
235
236 static void process_nice_level(void) {
src/inlined.h
+30 -8
@@ -244,26 +244,48 @@ static inline char *strncpyz(char *dst, const char *src, size_t n) {
244 return p;
245 }
246
247 -static inline int read_single_number_file(const char *filename, unsigned long long *result) {
248 - char buffer[30 + 1];
249 -
247 +static inline int read_file(const char *filename, char *buffer, size_t size) {
248 int fd = open(filename, O_RDONLY, 0666);
251 - if(unlikely(fd == -1)) {
252 - *result = 0;
249 + if(unlikely(fd == -1))
250 return 1;
254 - }
251
256 - ssize_t r = read(fd, buffer, 30);
252 + ssize_t r = read(fd, buffer, size);
253 if(unlikely(r == -1)) {
258 - *result = 0;
254 close(fd);
255 return 2;
256 }
257 + buffer[r] = '\0';
258
259 close(fd);
260 + return 0;
261 +}
262 +
263 +static inline int read_single_number_file(const char *filename, unsigned long long *result) {
264 + char buffer[30 + 1];
265 +
266 + int ret = read_file(filename, buffer, 30);
267 + if(unlikely(ret)) {
268 + *result = 0;
269 + return ret;
270 + }
271 +
272 buffer[30] = '\0';
273 *result = str2ull(buffer);
274 return 0;
275 }
276
277 +static inline int read_single_signed_number_file(const char *filename, long long *result) {
278 + char buffer[30 + 1];
279 +
280 + int ret = read_file(filename, buffer, 30);
281 + if(unlikely(ret)) {
282 + *result = 0;
283 + return ret;
284 + }
285 +
286 + buffer[30] = '\0';
287 + *result = atoll(buffer);
288 + return 0;
289 +}
290 +
291 #endif //NETDATA_INLINED_H
system/netdata.service.in
+6
@@ -8,6 +8,12 @@ User=netdata
8 Group=netdata
9 ExecStart=@sbindir_POST@/netdata -D
10
11 +# The minimum netdata Out-Of-Memory (OOM) score.
12 +# netdata (via [global].OOM score in netdata.conf) can only increase the value set here.
13 +# To decrease it, set the minimum here and set the same or a higher value in netdata.conf.
14 +# Valid values: -1000 (never kill netdata) to 1000 (always kill netdata).
15 +OOMScoreAdjust=0
16 +
17 # saving a big db on slow disks may need some time
18 TimeoutStopSec=60
19