Skip to content

Commit

Permalink
add --prefer-only option to only kill processes matching --prefer
Browse files Browse the repository at this point in the history
While --avoid exists to list processes that should not be killed, it may
be desirable to have earlyoom simply ignore any processes that do not
match the regex specified in --prefer. It should be noted that the Linux
kernel may still opt to kill other processes if earlyoom did not free up
enough memory to prevent an oom.

Signed-off-by: Murat Boyar <[email protected]>
Signed-off-by: Cedric Hombourger <[email protected]>
  • Loading branch information
chombourger committed Mar 11, 2024
1 parent c19f61a commit 687e820
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 5 deletions.
14 changes: 9 additions & 5 deletions kill.c
Original file line number Diff line number Diff line change
Expand Up @@ -309,11 +309,15 @@ bool is_larger(const poll_loop_args_t* args, const procinfo_t* victim, procinfo_
debug("pid %d: error reading process name: %s\n", cur->pid, strerror(-res));
return false;
}
if (args->prefer_regex && regexec(args->prefer_regex, cur->name, (size_t)0, NULL, 0) == 0) {
if (args->sort_by_rss) {
cur->VmRSSkiB += VMRSS_PREFER;
} else {
cur->badness += BADNESS_PREFER;
if (args->prefer_regex) {
if (regexec(args->prefer_regex, cur->name, (size_t)0, NULL, 0) == 0) {
if (args->sort_by_rss) {
cur->VmRSSkiB += VMRSS_PREFER;
} else {
cur->badness += BADNESS_PREFER;
}
} else if (args->prefer_only) {
return false;
}
}
if (args->avoid_regex && regexec(args->avoid_regex, cur->name, (size_t)0, NULL, 0) == 0) {
Expand Down
2 changes: 2 additions & 0 deletions kill.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ typedef struct {
int report_interval_ms;
/* Flag --dryrun was passed */
bool dryrun;
/* Flag --prefer-only was passed */
bool prefer_only;
} poll_loop_args_t;

void kill_process(const poll_loop_args_t* args, int sig, const procinfo_t* victim);
Expand Down
15 changes: 15 additions & 0 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ enum {
LONG_OPT_IGNORE_ROOT,
LONG_OPT_USE_SYSLOG,
LONG_OPT_SORT_BY_RSS,
LONG_OPT_PREFER_ONLY,
};

static int set_oom_score_adj(int);
Expand Down Expand Up @@ -129,6 +130,7 @@ int main(int argc, char* argv[])
const char* short_opt = "m:s:M:S:kingN:dvr:ph";
struct option long_opt[] = {
{ "prefer", required_argument, NULL, LONG_OPT_PREFER },
{ "prefer-only", no_argument, NULL, LONG_OPT_PREFER_ONLY },
{ "avoid", required_argument, NULL, LONG_OPT_AVOID },
{ "ignore", required_argument, NULL, LONG_OPT_IGNORE },
{ "dryrun", no_argument, NULL, LONG_OPT_DRYRUN },
Expand Down Expand Up @@ -234,6 +236,10 @@ int main(int argc, char* argv[])
case LONG_OPT_PREFER:
prefer_cmds = optarg;
break;
case LONG_OPT_PREFER_ONLY:
warn("prefer-only mode enabled, will only kill processes matching --prefer\n");
args.prefer_only = 1;
break;
case LONG_OPT_AVOID:
avoid_cmds = optarg;
break;
Expand Down Expand Up @@ -273,6 +279,7 @@ int main(int argc, char* argv[])
" --ignore-root-user do not kill processes owned by root\n"
" --sort-by-rss find process with the largest rss (default oom_score)\n"
" --prefer REGEX prefer to kill processes matching REGEX\n"
" --prefer-only only kill processes matched by --prefer\n"
" --avoid REGEX avoid killing processes matching REGEX\n"
" --ignore REGEX ignore processes matching REGEX\n"
" --dryrun dry run (do not kill any processes)\n"
Expand Down Expand Up @@ -324,6 +331,14 @@ int main(int argc, char* argv[])
}
fprintf(stderr, "Preferring to kill process names that match regex '%s'\n", prefer_cmds);
}
if (args.prefer_only) {
if (!prefer_cmds) {
fatal(EINVAL, "prefer-only requires --prefer\n");
} else if (avoid_cmds) {
avoid_cmds = NULL;
warn("prefer-only and --avoid are mutually exclusive, ignoring --avoid\n");
}
}
if (avoid_cmds) {
args.avoid_regex = &_avoid_regex;
if (regcomp(args.avoid_regex, avoid_cmds, REG_EXTENDED | REG_NOSUB) != 0) {
Expand Down
4 changes: 4 additions & 0 deletions testsuite_cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ func TestCli(t *testing.T) {
// Test --avoid, --prefer, --ignore-root-user and --sort-by-rss
{args: []string{"--avoid", "MyProcess1"}, code: -1, stderrContains: "Will avoid killing", stdoutContains: memReport},
{args: []string{"--prefer", "MyProcess2"}, code: -1, stderrContains: "Preferring to kill", stdoutContains: memReport},
{args: []string{"--prefer", "MyProcess1", "--prefer-only", "--avoid", "MyProcess2"}, code: -1, stderrContains: "prefer-only and --avoid are mutually", stdoutContains: memReport},
{args: []string{"--prefer", "MyProcess1", "--prefer-only"}, code: -1, stderrContains: "prefer-only mode enabled", stdoutContains: memReport},
{args: []string{"--avoid", "MyProcess2", "--prefer-only"}, code: 22, stderrContains: "fatal", stdoutEmpty: true},
{args: []string{"--prefer-only"}, code: 22, stderrContains: "fatal", stdoutEmpty: true},
{args: []string{"--ignore-root-user"}, code: -1, stderrContains: "Processes owned by root will not be killed", stdoutContains: memReport},
{args: []string{"--sort-by-rss"}, code: -1, stderrContains: "Find process with the largest rss", stdoutContains: memReport},
{args: []string{"-i"}, code: -1, stderrContains: "Option -i is ignored"},
Expand Down

0 comments on commit 687e820

Please sign in to comment.