Looks good to me on a first pass<br><br><div class="gmail_quote">On Mon, May 2, 2011 at 2:05 PM, Marc - A. Dahlhaus <span dir="ltr"><<a href="mailto:mad@wol.de">mad@wol.de</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div class="im">Am 17.03.2011 21:48, schrieb Scott James Remnant:<br>
</div><div><div></div><div class="h5">> (Replying to the new patch separately)<br>
><br>
> On Thu, Mar 17, 2011 at 11:58 AM, Marc - A. Dahlhaus <<a href="mailto:mad@wol.de">mad@wol.de</a>> wrote:<br>
><br>
>> The never case was no problem as i set booth values on never.<br>
>> But i get your point. Rewrote it per your comments. Result attached.<br>
>><br>
> This looks perfect, could you add some tests for "oom score" to the<br>
> parsing code, I see you've already updated the existing ones. It also<br>
> needs a man page update (I suggest just dropping "oom NN" out of the<br>
> man page and replacing it with "score")<br>
><br>
> Then it looks ready to apply!<br>
><br>
> Thankyou,<br>
> Scott<br>
<br>
</div></div>This should be it...<br>
<br>
Running for more weeks without any problem here.<br>
<br>
3 Test-Boxes (x86_64 and i686) did several boots, shutdowns and reboots<br>
no problems detected.<br>
<br>
thanks,<br>
<br>
Marc<br>
<div class="im"><br>
--- a/init/errors.h<br>
+++ b/init/errors.h<br>
@@ -62,7 +62,8 @@ enum {<br>
#define PARSE_ILLEGAL_EXIT_STR N_("Illegal exit status, expected integer")<br>
#define PARSE_ILLEGAL_UMASK_STR N_("Illegal file creation mask,<br>
expected octal integer")<br>
#define PARSE_ILLEGAL_NICE_STR N_("Illegal nice value, expected -20 to<br>
19")<br>
-#define PARSE_ILLEGAL_OOM_STR N_("Illegal oom adjustment, expected -16<br>
to 15 or never")<br>
+#define PARSE_ILLEGAL_OOM_STR N_("Illegal oom adjustment, expected -16<br>
to 15 or 'never'")<br>
+#define PARSE_ILLEGAL_OOM_SCORE_STR N_("Illegal oom score adjustment,<br>
expected -999 to 1000 or 'never'")<br>
#define PARSE_ILLEGAL_LIMIT_STR N_("Illegal limit, expected<br>
'unlimited' or integer")<br>
#define PARSE_EXPECTED_EVENT_STR N_("Expected event")<br>
#define PARSE_EXPECTED_OPERATOR_STR N_("Expected operator")<br>
--- a/init/job_class.c<br>
+++ b/init/job_class.c<br>
</div>@@ -211,7 +211,7 @@ job_class_new (const void *parent,<br>
<div class="im"><br>
class->umask = JOB_DEFAULT_UMASK;<br>
class->nice = 0;<br>
- class->oom_adj = 0;<br>
+ class->oom_score_adj = 0;<br>
<br>
for (i = 0; i < RLIMIT_NLIMITS; i++)<br>
class->limits[i] = NULL;<br>
</div><div class="im">--- a/init/job_class.h<br>
+++ b/init/job_class.h<br>
</div>@@ -93,7 +93,7 @@ typedef enum console_type {<br>
* @console: how to arrange processes' stdin/out/err file descriptors,<br>
<div class="im"> * @umask: file mode creation mask,<br>
* @nice: process priority,<br>
- * @oom_adj: OOM killer adjustment,<br>
+ * @oom_score_adj: OOM killer score adjustment,<br>
* @limits: resource limits indexed by resource,<br>
* @chroot: root directory of process (implies @chdir if not set),<br>
* @chdir: working directory of process,<br>
</div>@@ -141,7 +141,7 @@ typedef struct job_class {<br>
<div class="im"><br>
mode_t umask;<br>
int nice;<br>
- int oom_adj;<br>
+ int oom_score_adj;<br>
struct rlimit *limits[RLIMIT_NLIMITS];<br>
char *chroot;<br>
char *chdir;<br>
</div>@@ -150,6 +150,8 @@ typedef struct job_class {<br>
int debug;<br>
} JobClass;<br>
<br>
+#define SCORE_TO_ADJ(x) ((x * ((x < 0) ? 17 : 15)) / 1000)<br>
+#define ADJ_TO_SCORE(x) ((x * 1000) / ((x < 0) ? 17 : 15))<br>
<br>
NIH_BEGIN_EXTERN<br>
<div class="im"><br>
--- a/init/job_process.c<br>
+++ b/init/job_process.c<br>
</div>@@ -371,7 +371,7 @@ job_process_spawn (JobClass *class,<br>
<div class="im"> {<br>
sigset_t child_set, orig_set;<br>
pid_t pid;<br>
- int i, fds[2];<br>
+ int i, fds[2], oom_value;<br>
char filename[PATH_MAX];<br>
FILE *fd;<br>
<br>
</div>@@ -493,16 +493,22 @@ job_process_spawn (JobClass *class,<br>
<br>
/* Adjust the process OOM killer priority.<br>
*/<br>
- if (class->oom_adj) {<br>
+ if (class->oom_score_adj) {<br>
<div class="im"> snprintf (filename, sizeof (filename),<br>
- "/proc/%d/oom_adj", getpid ());<br>
</div>-<br>
+ "/proc/%d/oom_score_adj", getpid ());<br>
+ oom_value = class->oom_score_adj;<br>
fd = fopen (filename, "w");<br>
+ if ((! fd) && (errno == EACCES)) {<br>
+ snprintf (filename, sizeof (filename),<br>
<div class="im">+ "/proc/%d/oom_adj", getpid ());<br>
</div>+ oom_value = SCORE_TO_ADJ(class->oom_score_adj);<br>
<div class="im">+ fd = fopen (filename, "w");<br>
+ }<br>
if (! fd) {<br>
</div><div class="im"> nih_error_raise_system ();<br>
job_process_error_abort (fds[1], JOB_PROCESS_ERROR_OOM_ADJ, 0);<br>
} else {<br>
- fprintf (fd, "%d\n", class->oom_adj);<br>
+ fprintf (fd, "%d\n", oom_value);<br>
<br>
if (fclose (fd)) {<br>
nih_error_raise_system ();<br>
</div>--- a/init/man/init.5<br>
+++ b/init/man/init.5<br>
@@ -500,15 +500,15 @@ see<br>
for more details.<br>
.\"<br>
.TP<br>
-.B oom \fIADJUSTMENT\fR|\fBnever<br>
+.B oom score \fIADJUSTMENT\fR|\fBnever<br>
Normally the OOM killer regards all processes equally, this stanza<br>
advises the kernel to treat this job differently.<br>
<br>
.I ADJUSTMENT<br>
may be an integer value from<br>
-.I -16<br>
+.I -999<br>
(very unlikely to be killed by the OOM killer) up to<br>
-.I 14<br>
+.I 1000<br>
(very likely to be killed by the OOM killer). It may also be the special<br>
value<br>
.B never<br>
<div class="im">--- a/init/parse_job.c<br>
+++ b/init/parse_job.c<br>
</div>@@ -2233,6 +2233,7 @@ stanza_oom (JobClass *class,<br>
nih_local char *arg = NULL;<br>
char *endptr;<br>
size_t a_pos, a_lineno;<br>
+ int oom_adj;<br>
int ret = -1;<br>
<br>
nih_assert (class != NULL);<br>
@@ -2247,12 +2248,37 @@ stanza_oom (JobClass *class,<br>
if (! arg)<br>
goto finish;<br>
<br>
- if (! strcmp (arg, "never")) {<br>
- class->oom_adj = -17;<br>
<div class="im">+ if (! strcmp (arg, "score")) {<br>
+ nih_local char *scorearg = NULL;<br>
+<br>
</div>+ /* Update error position to the score value */<br>
+ *pos = a_pos;<br>
+ if (lineno)<br>
+ *lineno = a_lineno;<br>
<div class="im">+<br>
+ scorearg = nih_config_next_arg (NULL, file, len,<br>
+ &a_pos, &a_lineno);<br>
+ if (! scorearg)<br>
+ goto finish;<br>
+<br>
+ if (! strcmp (scorearg, "never")) {<br>
+ class->oom_score_adj = -1000;<br>
</div><div class="im">+ } else {<br>
+ errno = 0;<br>
+ class->oom_score_adj = (int)strtol (scorearg, &endptr, 10);<br>
</div><div class="im">+ if (errno || *endptr ||<br>
+ (class->oom_score_adj < -1000) ||<br>
+ (class->oom_score_adj > 1000))<br>
+ nih_return_error (-1, PARSE_ILLEGAL_OOM,<br>
+ _(PARSE_ILLEGAL_OOM_SCORE_STR));<br>
+ }<br>
</div>+ } else if (! strcmp (arg, "never")) {<br>
<div class="im">+ class->oom_score_adj = -1000;<br>
} else {<br>
errno = 0;<br>
- class->oom_adj = (int)strtol (arg, &endptr, 10);<br>
- if (errno || *endptr || (class->oom_adj < -17) || (class->oom_adj > 15))<br>
</div>+ oom_adj = (int)strtol (arg, &endptr, 10);<br>
+ class->oom_score_adj = ADJ_TO_SCORE(oom_adj);<br>
+ if (errno || *endptr || (oom_adj < -17) || (oom_adj > 15))<br>
<div class="im"> nih_return_error (-1, PARSE_ILLEGAL_OOM,<br>
_(PARSE_ILLEGAL_OOM_STR));<br>
}<br>
</div>--- a/init/tests/test_job_class.c<br>
+++ b/init/tests/test_job_class.c<br>
@@ -133,7 +133,7 @@ test_new (void)<br>
<br>
TEST_EQ (class->umask, 022);<br>
TEST_EQ (class->nice, 0);<br>
- TEST_EQ (class->oom_adj, 0);<br>
+ TEST_EQ (class->oom_score_adj, 0);<br>
<div class="im"><br>
for (i = 0; i < RLIMIT_NLIMITS; i++)<br>
</div> TEST_EQ_P (class->limits[i], NULL);<br>
--- a/init/tests/test_parse_job.c<br>
+++ b/init/tests/test_parse_job.c<br>
@@ -6198,11 +6198,39 @@ test_stanza_oom (void)<br>
<br>
TEST_ALLOC_SIZE (job, sizeof (JobClass));<br>
<br>
- TEST_EQ (job->oom_adj, 10);<br>
+ TEST_EQ (job->oom_score_adj, ADJ_TO_SCORE(10));<br>
<br>
nih_free (job);<br>
}<br>
<br>
+ TEST_FEATURE ("with positive score argument");<br>
+ strcpy (buf, "oom score 100\n");<br>
+<br>
+ TEST_ALLOC_FAIL {<br>
+ pos = 0;<br>
+ lineno = 1;<br>
+ job = parse_job (NULL, "test", buf, strlen (buf),<br>
+ &pos, &lineno);<br>
+<br>
+ if (test_alloc_failed) {<br>
+ TEST_EQ_P (job, NULL);<br>
+<br>
+ err = nih_error_get ();<br>
+ TEST_EQ (err->number, ENOMEM);<br>
+ nih_free (err);<br>
+<br>
+ continue;<br>
+ }<br>
+<br>
+ TEST_EQ (pos, strlen (buf));<br>
+ TEST_EQ (lineno, 2);<br>
+<br>
+ TEST_ALLOC_SIZE (job, sizeof (JobClass));<br>
+<br>
+ TEST_EQ (job->oom_score_adj, 100);<br>
+<br>
+ nih_free (job);<br>
+ }<br>
<br>
/* Check that an oom stanza with a negative timeout results<br>
* in it being stored in the job.<br>
@@ -6231,7 +6259,36 @@ test_stanza_oom (void)<br>
<br>
TEST_ALLOC_SIZE (job, sizeof (JobClass));<br>
<br>
- TEST_EQ (job->oom_adj, -10);<br>
+ TEST_EQ (job->oom_score_adj, ADJ_TO_SCORE(-10));<br>
+<br>
+ nih_free (job);<br>
+ }<br>
+<br>
+ TEST_FEATURE ("with negative score argument");<br>
+ strcpy (buf, "oom score -100\n");<br>
+<br>
+ TEST_ALLOC_FAIL {<br>
+ pos = 0;<br>
+ lineno = 1;<br>
+ job = parse_job (NULL, "test", buf, strlen (buf),<br>
+ &pos, &lineno);<br>
+<br>
+ if (test_alloc_failed) {<br>
+ TEST_EQ_P (job, NULL);<br>
+<br>
+ err = nih_error_get ();<br>
+ TEST_EQ (err->number, ENOMEM);<br>
+ nih_free (err);<br>
+<br>
+ continue;<br>
+ }<br>
+<br>
+ TEST_EQ (pos, strlen (buf));<br>
+ TEST_EQ (lineno, 2);<br>
+<br>
+ TEST_ALLOC_SIZE (job, sizeof (JobClass));<br>
+<br>
+ TEST_EQ (job->oom_score_adj, -100);<br>
<br>
nih_free (job);<br>
}<br>
@@ -6264,7 +6321,40 @@ test_stanza_oom (void)<br>
<br>
TEST_ALLOC_SIZE (job, sizeof (JobClass));<br>
<br>
- TEST_EQ (job->oom_adj, -17);<br>
+ TEST_EQ (job->oom_score_adj, ADJ_TO_SCORE(-17));<br>
+<br>
+ nih_free (job);<br>
+ }<br>
+<br>
+<br>
+ /* Check that an oom score stanza may have the special never<br>
+ * argument which stores -1000 in the job.<br>
+ */<br>
+ TEST_FEATURE ("with never score argument");<br>
+ strcpy (buf, "oom score never\n");<br>
+<br>
+ TEST_ALLOC_FAIL {<br>
+ pos = 0;<br>
+ lineno = 1;<br>
+ job = parse_job (NULL, "test", buf, strlen (buf),<br>
+ &pos, &lineno);<br>
+<br>
+ if (test_alloc_failed) {<br>
+ TEST_EQ_P (job, NULL);<br>
+<br>
+ err = nih_error_get ();<br>
+ TEST_EQ (err->number, ENOMEM);<br>
+ nih_free (err);<br>
+<br>
+ continue;<br>
+ }<br>
+<br>
+ TEST_EQ (pos, strlen (buf));<br>
+ TEST_EQ (lineno, 2);<br>
+<br>
+ TEST_ALLOC_SIZE (job, sizeof (JobClass));<br>
+<br>
+ TEST_EQ (job->oom_score_adj, -1000);<br>
<br>
nih_free (job);<br>
}<br>
@@ -6297,7 +6387,100 @@ test_stanza_oom (void)<br>
<br>
TEST_ALLOC_SIZE (job, sizeof (JobClass));<br>
<br>
- TEST_EQ (job->oom_adj, 10);<br>
+ TEST_EQ (job->oom_score_adj, ADJ_TO_SCORE(10));<br>
+<br>
+ nih_free (job);<br>
+ }<br>
+<br>
+ TEST_FEATURE ("with multiple score stanzas");<br>
+ strcpy (buf, "oom score -500\n");<br>
+ strcat (buf, "oom score 500\n");<br>
+<br>
+ TEST_ALLOC_FAIL {<br>
+ pos = 0;<br>
+ lineno = 1;<br>
+ job = parse_job (NULL, "test", buf, strlen (buf),<br>
+ &pos, &lineno);<br>
+<br>
+ if (test_alloc_failed) {<br>
+ TEST_EQ_P (job, NULL);<br>
+<br>
+ err = nih_error_get ();<br>
+ TEST_EQ (err->number, ENOMEM);<br>
+ nih_free (err);<br>
+<br>
+ continue;<br>
+ }<br>
+<br>
+ TEST_EQ (pos, strlen (buf));<br>
+ TEST_EQ (lineno, 3);<br>
+<br>
+ TEST_ALLOC_SIZE (job, sizeof (JobClass));<br>
+<br>
+ TEST_EQ (job->oom_score_adj, 500);<br>
+<br>
+ nih_free (job);<br>
+ }<br>
+<br>
+ /* Check that the last of multiple distinct oom stanzas is<br>
+ * used.<br>
+ */<br>
+ TEST_FEATURE ("with an oom overriding an oom score stanza");<br>
+ strcpy (buf, "oom score -10\n");<br>
+ strcat (buf, "oom 10\n");<br>
+<br>
+ TEST_ALLOC_FAIL {<br>
+ pos = 0;<br>
+ lineno = 1;<br>
+ job = parse_job (NULL, "test", buf, strlen (buf),<br>
+ &pos, &lineno);<br>
+<br>
+ if (test_alloc_failed) {<br>
+ TEST_EQ_P (job, NULL);<br>
+<br>
+ err = nih_error_get ();<br>
+ TEST_EQ (err->number, ENOMEM);<br>
+ nih_free (err);<br>
+<br>
+ continue;<br>
+ }<br>
+<br>
+ TEST_EQ (pos, strlen (buf));<br>
+ TEST_EQ (lineno, 3);<br>
+<br>
+ TEST_ALLOC_SIZE (job, sizeof (JobClass));<br>
+<br>
+ TEST_EQ (job->oom_score_adj, ADJ_TO_SCORE(10));<br>
+<br>
+ nih_free (job);<br>
+ }<br>
+<br>
+ TEST_FEATURE ("with an oom score overriding an oom stanza");<br>
+ strcpy (buf, "oom -10\n");<br>
+ strcat (buf, "oom score 10\n");<br>
+<br>
+ TEST_ALLOC_FAIL {<br>
+ pos = 0;<br>
+ lineno = 1;<br>
+ job = parse_job (NULL, "test", buf, strlen (buf),<br>
+ &pos, &lineno);<br>
+<br>
+ if (test_alloc_failed) {<br>
+ TEST_EQ_P (job, NULL);<br>
+<br>
+ err = nih_error_get ();<br>
+ TEST_EQ (err->number, ENOMEM);<br>
+ nih_free (err);<br>
+<br>
+ continue;<br>
+ }<br>
+<br>
+ TEST_EQ (pos, strlen (buf));<br>
+ TEST_EQ (lineno, 3);<br>
+<br>
+ TEST_ALLOC_SIZE (job, sizeof (JobClass));<br>
+<br>
+ TEST_EQ (job->oom_score_adj, 10);<br>
<br>
nih_free (job);<br>
}<br>
@@ -6322,6 +6505,25 @@ test_stanza_oom (void)<br>
nih_free (err);<br>
<br>
<br>
+ /* Check that an oom score stanza without an argument results in a<br>
+ * syntax error.<br>
+ */<br>
+ TEST_FEATURE ("with missing score argument");<br>
+ strcpy (buf, "oom score\n");<br>
+<br>
+ pos = 0;<br>
+ lineno = 1;<br>
+ job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);<br>
+<br>
+ TEST_EQ_P (job, NULL);<br>
+<br>
+ err = nih_error_get ();<br>
+ TEST_EQ (err->number, NIH_CONFIG_EXPECTED_TOKEN);<br>
+ TEST_EQ (pos, 9);<br>
+ TEST_EQ (lineno, 1);<br>
+ nih_free (err);<br>
+<br>
+<br>
/* Check that an oom stanza with an overly large argument results<br>
* in a syntax error.<br>
*/<br>
@@ -6340,6 +6542,21 @@ test_stanza_oom (void)<br>
TEST_EQ (lineno, 1);<br>
nih_free (err);<br>
<br>
+ TEST_FEATURE ("with overly large score argument");<br>
+ strcpy (buf, "oom score 1200\n");<br>
+<br>
+ pos = 0;<br>
+ lineno = 1;<br>
+ job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);<br>
+<br>
+ TEST_EQ_P (job, NULL);<br>
+<br>
+ err = nih_error_get ();<br>
+ TEST_EQ (err->number, PARSE_ILLEGAL_OOM);<br>
+ TEST_EQ (pos, 10);<br>
+ TEST_EQ (lineno, 1);<br>
+ nih_free (err);<br>
+<br>
<br>
/* Check that an oom stanza with an overly small argument results<br>
* in a syntax error.<br>
@@ -6359,6 +6576,21 @@ test_stanza_oom (void)<br>
TEST_EQ (lineno, 1);<br>
nih_free (err);<br>
<br>
+ TEST_FEATURE ("with overly small score argument");<br>
+ strcpy (buf, "oom score -1200\n");<br>
+<br>
+ pos = 0;<br>
+ lineno = 1;<br>
+ job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);<br>
+<br>
+ TEST_EQ_P (job, NULL);<br>
+<br>
+ err = nih_error_get ();<br>
+ TEST_EQ (err->number, PARSE_ILLEGAL_OOM);<br>
+ TEST_EQ (pos, 10);<br>
+ TEST_EQ (lineno, 1);<br>
+ nih_free (err);<br>
+<br>
<br>
/* Check that an oom stanza with a non-integer argument results<br>
* in a syntax error.<br>
@@ -6378,6 +6610,21 @@ test_stanza_oom (void)<br>
TEST_EQ (lineno, 1);<br>
nih_free (err);<br>
<br>
+ TEST_FEATURE ("with non-integer score argument");<br>
+ strcpy (buf, "oom score foo\n");<br>
+<br>
+ pos = 0;<br>
+ lineno = 1;<br>
+ job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);<br>
+<br>
+ TEST_EQ_P (job, NULL);<br>
+<br>
+ err = nih_error_get ();<br>
+ TEST_EQ (err->number, PARSE_ILLEGAL_OOM);<br>
+ TEST_EQ (pos, 10);<br>
+ TEST_EQ (lineno, 1);<br>
+ nih_free (err);<br>
+<br>
<br>
/* Check that an oom stanza with a partially numeric argument<br>
* results in a syntax error.<br>
@@ -6397,6 +6644,21 @@ test_stanza_oom (void)<br>
TEST_EQ (lineno, 1);<br>
nih_free (err);<br>
<br>
+ TEST_FEATURE ("with alphanumeric score argument");<br>
+ strcpy (buf, "oom score 12foo\n");<br>
+<br>
+ pos = 0;<br>
+ lineno = 1;<br>
+ job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);<br>
+<br>
+ TEST_EQ_P (job, NULL);<br>
+<br>
+ err = nih_error_get ();<br>
+ TEST_EQ (err->number, PARSE_ILLEGAL_OOM);<br>
+ TEST_EQ (pos, 10);<br>
+ TEST_EQ (lineno, 1);<br>
+ nih_free (err);<br>
+<br>
<br>
/* Check that an oom stanza with a priority but with an extra<br>
* argument afterwards results in a syntax error.<br>
@@ -6415,6 +6677,21 @@ test_stanza_oom (void)<br>
TEST_EQ (pos, 7);<br>
TEST_EQ (lineno, 1);<br>
nih_free (err);<br>
+<br>
+ TEST_FEATURE ("with extra score argument");<br>
+ strcpy (buf, "oom score 500 foo\n");<br>
+<br>
+ pos = 0;<br>
+ lineno = 1;<br>
+ job = parse_job (NULL, "test", buf, strlen (buf), &pos, &lineno);<br>
+<br>
+ TEST_EQ_P (job, NULL);<br>
+<br>
+ err = nih_error_get ();<br>
+ TEST_EQ (err->number, NIH_CONFIG_UNEXPECTED_TOKEN);<br>
+ TEST_EQ (pos, 14);<br>
+ TEST_EQ (lineno, 1);<br>
+ nih_free (err);<br>
}<br>
<br>
void<br>
</blockquote></div><br>