Merge lp:~mad-wol/upstart/oom-score-stanza into lp:upstart

Proposed by Marc - A. Dahlhaus
Status: Merged
Merged at revision: 1281
Proposed branch: lp:~mad-wol/upstart/oom-score-stanza
Merge into: lp:upstart
Diff against target: 554 lines (+337/-25)
8 files modified
init/errors.h (+2/-1)
init/job_class.c (+1/-1)
init/job_class.h (+4/-2)
init/job_process.c (+11/-5)
init/man/init.5 (+3/-3)
init/parse_job.c (+30/-4)
init/tests/test_job_class.c (+1/-1)
init/tests/test_parse_job.c (+285/-8)
To merge this branch: bzr merge lp:~mad-wol/upstart/oom-score-stanza
Reviewer Review Type Date Requested Status
Scott James Remnant Pending
Review via email: mp+60037@code.launchpad.net

Description of the change

This adds support for the oom_score_adj procfs api.

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'init/errors.h'
2--- init/errors.h 2009-06-23 09:29:35 +0000
3+++ init/errors.h 2011-05-05 10:18:25 +0000
4@@ -62,7 +62,8 @@
5 #define PARSE_ILLEGAL_EXIT_STR N_("Illegal exit status, expected integer")
6 #define PARSE_ILLEGAL_UMASK_STR N_("Illegal file creation mask, expected octal integer")
7 #define PARSE_ILLEGAL_NICE_STR N_("Illegal nice value, expected -20 to 19")
8-#define PARSE_ILLEGAL_OOM_STR N_("Illegal oom adjustment, expected -16 to 15 or never")
9+#define PARSE_ILLEGAL_OOM_STR N_("Illegal oom adjustment, expected -16 to 15 or 'never'")
10+#define PARSE_ILLEGAL_OOM_SCORE_STR N_("Illegal oom score adjustment, expected -999 to 1000 or 'never'")
11 #define PARSE_ILLEGAL_LIMIT_STR N_("Illegal limit, expected 'unlimited' or integer")
12 #define PARSE_EXPECTED_EVENT_STR N_("Expected event")
13 #define PARSE_EXPECTED_OPERATOR_STR N_("Expected operator")
14
15=== modified file 'init/job_class.c'
16--- init/job_class.c 2010-12-14 15:30:06 +0000
17+++ init/job_class.c 2011-05-05 10:18:25 +0000
18@@ -211,7 +211,7 @@
19
20 class->umask = JOB_DEFAULT_UMASK;
21 class->nice = 0;
22- class->oom_adj = 0;
23+ class->oom_score_adj = 0;
24
25 for (i = 0; i < RLIMIT_NLIMITS; i++)
26 class->limits[i] = NULL;
27
28=== modified file 'init/job_class.h'
29--- init/job_class.h 2010-12-14 15:30:06 +0000
30+++ init/job_class.h 2011-05-05 10:18:25 +0000
31@@ -93,7 +93,7 @@
32 * @console: how to arrange processes' stdin/out/err file descriptors,
33 * @umask: file mode creation mask,
34 * @nice: process priority,
35- * @oom_adj: OOM killer adjustment,
36+ * @oom_score_adj: OOM killer score adjustment,
37 * @limits: resource limits indexed by resource,
38 * @chroot: root directory of process (implies @chdir if not set),
39 * @chdir: working directory of process,
40@@ -141,7 +141,7 @@
41
42 mode_t umask;
43 int nice;
44- int oom_adj;
45+ int oom_score_adj;
46 struct rlimit *limits[RLIMIT_NLIMITS];
47 char *chroot;
48 char *chdir;
49@@ -150,6 +150,8 @@
50 int debug;
51 } JobClass;
52
53+#define SCORE_TO_ADJ(x) ((x * ((x < 0) ? 17 : 15)) / 1000)
54+#define ADJ_TO_SCORE(x) ((x * 1000) / ((x < 0) ? 17 : 15))
55
56 NIH_BEGIN_EXTERN
57
58
59=== modified file 'init/job_process.c'
60--- init/job_process.c 2011-03-22 17:46:46 +0000
61+++ init/job_process.c 2011-05-05 10:18:25 +0000
62@@ -371,7 +371,7 @@
63 {
64 sigset_t child_set, orig_set;
65 pid_t pid;
66- int i, fds[2];
67+ int i, fds[2], oom_value;
68 char filename[PATH_MAX];
69 FILE *fd;
70
71@@ -493,16 +493,22 @@
72
73 /* Adjust the process OOM killer priority.
74 */
75- if (class->oom_adj) {
76+ if (class->oom_score_adj) {
77 snprintf (filename, sizeof (filename),
78- "/proc/%d/oom_adj", getpid ());
79-
80+ "/proc/%d/oom_score_adj", getpid ());
81+ oom_value = class->oom_score_adj;
82 fd = fopen (filename, "w");
83+ if ((! fd) && (errno == EACCES)) {
84+ snprintf (filename, sizeof (filename),
85+ "/proc/%d/oom_adj", getpid ());
86+ oom_value = SCORE_TO_ADJ(class->oom_score_adj);
87+ fd = fopen (filename, "w");
88+ }
89 if (! fd) {
90 nih_error_raise_system ();
91 job_process_error_abort (fds[1], JOB_PROCESS_ERROR_OOM_ADJ, 0);
92 } else {
93- fprintf (fd, "%d\n", class->oom_adj);
94+ fprintf (fd, "%d\n", oom_value);
95
96 if (fclose (fd)) {
97 nih_error_raise_system ();
98
99=== modified file 'init/man/init.5'
100--- init/man/init.5 2011-03-15 18:36:57 +0000
101+++ init/man/init.5 2011-05-05 10:18:25 +0000
102@@ -500,15 +500,15 @@
103 for more details.
104 .\"
105 .TP
106-.B oom \fIADJUSTMENT\fR|\fBnever
107+.B oom score \fIADJUSTMENT\fR|\fBnever
108 Normally the OOM killer regards all processes equally, this stanza
109 advises the kernel to treat this job differently.
110
111 .I ADJUSTMENT
112 may be an integer value from
113-.I -16
114+.I -999
115 (very unlikely to be killed by the OOM killer) up to
116-.I 14
117+.I 1000
118 (very likely to be killed by the OOM killer). It may also be the special
119 value
120 .B never
121
122=== modified file 'init/parse_job.c'
123--- init/parse_job.c 2011-01-17 16:37:54 +0000
124+++ init/parse_job.c 2011-05-05 10:18:25 +0000
125@@ -2233,6 +2233,7 @@
126 nih_local char *arg = NULL;
127 char *endptr;
128 size_t a_pos, a_lineno;
129+ int oom_adj;
130 int ret = -1;
131
132 nih_assert (class != NULL);
133@@ -2247,12 +2248,37 @@
134 if (! arg)
135 goto finish;
136
137- if (! strcmp (arg, "never")) {
138- class->oom_adj = -17;
139+ if (! strcmp (arg, "score")) {
140+ nih_local char *scorearg = NULL;
141+
142+ /* Update error position to the score value */
143+ *pos = a_pos;
144+ if (lineno)
145+ *lineno = a_lineno;
146+
147+ scorearg = nih_config_next_arg (NULL, file, len,
148+ &a_pos, &a_lineno);
149+ if (! scorearg)
150+ goto finish;
151+
152+ if (! strcmp (scorearg, "never")) {
153+ class->oom_score_adj = -1000;
154+ } else {
155+ errno = 0;
156+ class->oom_score_adj = (int)strtol (scorearg, &endptr, 10);
157+ if (errno || *endptr ||
158+ (class->oom_score_adj < -1000) ||
159+ (class->oom_score_adj > 1000))
160+ nih_return_error (-1, PARSE_ILLEGAL_OOM,
161+ _(PARSE_ILLEGAL_OOM_SCORE_STR));
162+ }
163+ } else if (! strcmp (arg, "never")) {
164+ class->oom_score_adj = -1000;
165 } else {
166 errno = 0;
167- class->oom_adj = (int)strtol (arg, &endptr, 10);
168- if (errno || *endptr || (class->oom_adj < -17) || (class->oom_adj > 15))
169+ oom_adj = (int)strtol (arg, &endptr, 10);
170+ class->oom_score_adj = ADJ_TO_SCORE(oom_adj);
171+ if (errno || *endptr || (oom_adj < -17) || (oom_adj > 15))
172 nih_return_error (-1, PARSE_ILLEGAL_OOM,
173 _(PARSE_ILLEGAL_OOM_STR));
174 }
175
176=== modified file 'init/tests/test_job_class.c'
177--- init/tests/test_job_class.c 2011-03-16 22:42:48 +0000
178+++ init/tests/test_job_class.c 2011-05-05 10:18:25 +0000
179@@ -133,7 +133,7 @@
180
181 TEST_EQ (class->umask, 022);
182 TEST_EQ (class->nice, 0);
183- TEST_EQ (class->oom_adj, 0);
184+ TEST_EQ (class->oom_score_adj, 0);
185
186 for (i = 0; i < RLIMIT_NLIMITS; i++)
187 TEST_EQ_P (class->limits[i], NULL);
188
189=== modified file 'init/tests/test_parse_job.c'
190--- init/tests/test_parse_job.c 2010-12-14 16:20:38 +0000
191+++ init/tests/test_parse_job.c 2011-05-05 10:18:25 +0000
192@@ -6198,11 +6198,39 @@
193
194 TEST_ALLOC_SIZE (job, sizeof (JobClass));
195
196- TEST_EQ (job->oom_adj, 10);
197-
198- nih_free (job);
199- }
200-
201+ TEST_EQ (job->oom_score_adj, ADJ_TO_SCORE(10));
202+
203+ nih_free (job);
204+ }
205+
206+ TEST_FEATURE ("with positive score argument");
207+ strcpy (buf, "oom score 100\n");
208+
209+ TEST_ALLOC_FAIL {
210+ pos = 0;
211+ lineno = 1;
212+ job = parse_job (NULL, "test", buf, strlen (buf),
213+ &pos, &lineno);
214+
215+ if (test_alloc_failed) {
216+ TEST_EQ_P (job, NULL);
217+
218+ err = nih_error_get ();
219+ TEST_EQ (err->number, ENOMEM);
220+ nih_free (err);
221+
222+ continue;
223+ }
224+
225+ TEST_EQ (pos, strlen (buf));
226+ TEST_EQ (lineno, 2);
227+
228+ TEST_ALLOC_SIZE (job, sizeof (JobClass));
229+
230+ TEST_EQ (job->oom_score_adj, 100);
231+
232+ nih_free (job);
233+ }
234
235 /* Check that an oom stanza with a negative timeout results
236 * in it being stored in the job.
237@@ -6231,7 +6259,36 @@
238
239 TEST_ALLOC_SIZE (job, sizeof (JobClass));
240
241- TEST_EQ (job->oom_adj, -10);
242+ TEST_EQ (job->oom_score_adj, ADJ_TO_SCORE(-10));
243+
244+ nih_free (job);
245+ }
246+
247+ TEST_FEATURE ("with negative score argument");
248+ strcpy (buf, "oom score -100\n");
249+
250+ TEST_ALLOC_FAIL {
251+ pos = 0;
252+ lineno = 1;
253+ job = parse_job (NULL, "test", buf, strlen (buf),
254+ &pos, &lineno);
255+
256+ if (test_alloc_failed) {
257+ TEST_EQ_P (job, NULL);
258+
259+ err = nih_error_get ();
260+ TEST_EQ (err->number, ENOMEM);
261+ nih_free (err);
262+
263+ continue;
264+ }
265+
266+ TEST_EQ (pos, strlen (buf));
267+ TEST_EQ (lineno, 2);
268+
269+ TEST_ALLOC_SIZE (job, sizeof (JobClass));
270+
271+ TEST_EQ (job->oom_score_adj, -100);
272
273 nih_free (job);
274 }
275@@ -6264,7 +6321,40 @@
276
277 TEST_ALLOC_SIZE (job, sizeof (JobClass));
278
279- TEST_EQ (job->oom_adj, -17);
280+ TEST_EQ (job->oom_score_adj, ADJ_TO_SCORE(-17));
281+
282+ nih_free (job);
283+ }
284+
285+
286+ /* Check that an oom score stanza may have the special never
287+ * argument which stores -1000 in the job.
288+ */
289+ TEST_FEATURE ("with never score argument");
290+ strcpy (buf, "oom score never\n");
291+
292+ TEST_ALLOC_FAIL {
293+ pos = 0;
294+ lineno = 1;
295+ job = parse_job (NULL, "test", buf, strlen (buf),
296+ &pos, &lineno);
297+
298+ if (test_alloc_failed) {
299+ TEST_EQ_P (job, NULL);
300+
301+ err = nih_error_get ();
302+ TEST_EQ (err->number, ENOMEM);
303+ nih_free (err);
304+
305+ continue;
306+ }
307+
308+ TEST_EQ (pos, strlen (buf));
309+ TEST_EQ (lineno, 2);
310+
311+ TEST_ALLOC_SIZE (job, sizeof (JobClass));
312+
313+ TEST_EQ (job->oom_score_adj, -1000);
314
315 nih_free (job);
316 }
317@@ -6297,7 +6387,100 @@
318
319 TEST_ALLOC_SIZE (job, sizeof (JobClass));
320
321- TEST_EQ (job->oom_adj, 10);
322+ TEST_EQ (job->oom_score_adj, ADJ_TO_SCORE(10));
323+
324+ nih_free (job);
325+ }
326+
327+ TEST_FEATURE ("with multiple score stanzas");
328+ strcpy (buf, "oom score -500\n");
329+ strcat (buf, "oom score 500\n");
330+
331+ TEST_ALLOC_FAIL {
332+ pos = 0;
333+ lineno = 1;
334+ job = parse_job (NULL, "test", buf, strlen (buf),
335+ &pos, &lineno);
336+
337+ if (test_alloc_failed) {
338+ TEST_EQ_P (job, NULL);
339+
340+ err = nih_error_get ();
341+ TEST_EQ (err->number, ENOMEM);
342+ nih_free (err);
343+
344+ continue;
345+ }
346+
347+ TEST_EQ (pos, strlen (buf));
348+ TEST_EQ (lineno, 3);
349+
350+ TEST_ALLOC_SIZE (job, sizeof (JobClass));
351+
352+ TEST_EQ (job->oom_score_adj, 500);
353+
354+ nih_free (job);
355+ }
356+
357+ /* Check that the last of multiple distinct oom stanzas is
358+ * used.
359+ */
360+ TEST_FEATURE ("with an oom overriding an oom score stanza");
361+ strcpy (buf, "oom score -10\n");
362+ strcat (buf, "oom 10\n");
363+
364+ TEST_ALLOC_FAIL {
365+ pos = 0;
366+ lineno = 1;
367+ job = parse_job (NULL, "test", buf, strlen (buf),
368+ &pos, &lineno);
369+
370+ if (test_alloc_failed) {
371+ TEST_EQ_P (job, NULL);
372+
373+ err = nih_error_get ();
374+ TEST_EQ (err->number, ENOMEM);
375+ nih_free (err);
376+
377+ continue;
378+ }
379+
380+ TEST_EQ (pos, strlen (buf));
381+ TEST_EQ (lineno, 3);
382+
383+ TEST_ALLOC_SIZE (job, sizeof (JobClass));
384+
385+ TEST_EQ (job->oom_score_adj, ADJ_TO_SCORE(10));
386+
387+ nih_free (job);
388+ }
389+
390+ TEST_FEATURE ("with an oom score overriding an oom stanza");
391+ strcpy (buf, "oom -10\n");
392+ strcat (buf, "oom score 10\n");
393+
394+ TEST_ALLOC_FAIL {
395+ pos = 0;
396+ lineno = 1;
397+ job = parse_job (NULL, "test", buf, strlen (buf),
398+ &pos, &lineno);
399+
400+ if (test_alloc_failed) {
401+ TEST_EQ_P (job, NULL);
402+
403+ err = nih_error_get ();
404+ TEST_EQ (err->number, ENOMEM);
405+ nih_free (err);
406+
407+ continue;
408+ }
409+
410+ TEST_EQ (pos, strlen (buf));
411+ TEST_EQ (lineno, 3);
412+
413+ TEST_ALLOC_SIZE (job, sizeof (JobClass));
414+
415+ TEST_EQ (job->oom_score_adj, 10);
416
417 nih_free (job);
418 }
419@@ -6322,6 +6505,25 @@
420 nih_free (err);
421
422
423+ /* Check that an oom score stanza without an argument results in a
424+ * syntax error.
425+ */
426+ TEST_FEATURE ("with missing score argument");
427+ strcpy (buf, "oom score\n");
428+
429+ pos = 0;
430+ lineno = 1;
431+ job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
432+
433+ TEST_EQ_P (job, NULL);
434+
435+ err = nih_error_get ();
436+ TEST_EQ (err->number, NIH_CONFIG_EXPECTED_TOKEN);
437+ TEST_EQ (pos, 9);
438+ TEST_EQ (lineno, 1);
439+ nih_free (err);
440+
441+
442 /* Check that an oom stanza with an overly large argument results
443 * in a syntax error.
444 */
445@@ -6340,6 +6542,21 @@
446 TEST_EQ (lineno, 1);
447 nih_free (err);
448
449+ TEST_FEATURE ("with overly large score argument");
450+ strcpy (buf, "oom score 1200\n");
451+
452+ pos = 0;
453+ lineno = 1;
454+ job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
455+
456+ TEST_EQ_P (job, NULL);
457+
458+ err = nih_error_get ();
459+ TEST_EQ (err->number, PARSE_ILLEGAL_OOM);
460+ TEST_EQ (pos, 10);
461+ TEST_EQ (lineno, 1);
462+ nih_free (err);
463+
464
465 /* Check that an oom stanza with an overly small argument results
466 * in a syntax error.
467@@ -6359,6 +6576,21 @@
468 TEST_EQ (lineno, 1);
469 nih_free (err);
470
471+ TEST_FEATURE ("with overly small score argument");
472+ strcpy (buf, "oom score -1200\n");
473+
474+ pos = 0;
475+ lineno = 1;
476+ job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
477+
478+ TEST_EQ_P (job, NULL);
479+
480+ err = nih_error_get ();
481+ TEST_EQ (err->number, PARSE_ILLEGAL_OOM);
482+ TEST_EQ (pos, 10);
483+ TEST_EQ (lineno, 1);
484+ nih_free (err);
485+
486
487 /* Check that an oom stanza with a non-integer argument results
488 * in a syntax error.
489@@ -6378,6 +6610,21 @@
490 TEST_EQ (lineno, 1);
491 nih_free (err);
492
493+ TEST_FEATURE ("with non-integer score argument");
494+ strcpy (buf, "oom score foo\n");
495+
496+ pos = 0;
497+ lineno = 1;
498+ job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
499+
500+ TEST_EQ_P (job, NULL);
501+
502+ err = nih_error_get ();
503+ TEST_EQ (err->number, PARSE_ILLEGAL_OOM);
504+ TEST_EQ (pos, 10);
505+ TEST_EQ (lineno, 1);
506+ nih_free (err);
507+
508
509 /* Check that an oom stanza with a partially numeric argument
510 * results in a syntax error.
511@@ -6397,6 +6644,21 @@
512 TEST_EQ (lineno, 1);
513 nih_free (err);
514
515+ TEST_FEATURE ("with alphanumeric score argument");
516+ strcpy (buf, "oom score 12foo\n");
517+
518+ pos = 0;
519+ lineno = 1;
520+ job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
521+
522+ TEST_EQ_P (job, NULL);
523+
524+ err = nih_error_get ();
525+ TEST_EQ (err->number, PARSE_ILLEGAL_OOM);
526+ TEST_EQ (pos, 10);
527+ TEST_EQ (lineno, 1);
528+ nih_free (err);
529+
530
531 /* Check that an oom stanza with a priority but with an extra
532 * argument afterwards results in a syntax error.
533@@ -6415,6 +6677,21 @@
534 TEST_EQ (pos, 7);
535 TEST_EQ (lineno, 1);
536 nih_free (err);
537+
538+ TEST_FEATURE ("with extra score argument");
539+ strcpy (buf, "oom score 500 foo\n");
540+
541+ pos = 0;
542+ lineno = 1;
543+ job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);
544+
545+ TEST_EQ_P (job, NULL);
546+
547+ err = nih_error_get ();
548+ TEST_EQ (err->number, NIH_CONFIG_UNEXPECTED_TOKEN);
549+ TEST_EQ (pos, 14);
550+ TEST_EQ (lineno, 1);
551+ nih_free (err);
552 }
553
554 void

Subscribers

People subscribed via source and target branches