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