Skip to content

Commit

Permalink
Allow SIGTERM value below SIGKILL
Browse files Browse the repository at this point in the history
Saying

  earlyoom -m 0,15

disables SIGTERM completely. Allow it.

#97
  • Loading branch information
rfjakob committed Nov 1, 2018
1 parent b1c0483 commit 28084c3
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 28 deletions.
23 changes: 11 additions & 12 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -331,19 +331,18 @@ static void poll_loop(const poll_loop_args_t args)
const int cooldown_ms = 200;

while (1) {
int sig = 0;
m = parse_meminfo();

if (m.MemAvailablePercent <= args.mem_term_percent && m.SwapFreePercent <= args.swap_term_percent) {
int sig = 0;
if (m.MemAvailablePercent <= args.mem_kill_percent && m.SwapFreePercent <= args.swap_kill_percent) {
warn("Low memory! At or below SIGKILL limits (mem: %d %%, swap: %d %%)\n",
args.mem_kill_percent, args.swap_kill_percent);
sig = SIGKILL;
} else {
warn("Low Memory! At or below SIGTERM limits (mem: %d %%, swap: %d %%)\n",
args.mem_term_percent, args.swap_term_percent);
sig = SIGTERM;
}
if (m.MemAvailablePercent <= args.mem_kill_percent && m.SwapFreePercent <= args.swap_kill_percent) {
warn("Low memory! At or below SIGKILL limits (mem: %d %%, swap: %d %%)\n",
args.mem_kill_percent, args.swap_kill_percent);
sig = SIGKILL;
} else if (m.MemAvailablePercent <= args.mem_term_percent && m.SwapFreePercent <= args.swap_term_percent) {
warn("Low Memory! At or below SIGTERM limits (mem: %d %%, swap: %d %%)\n",
args.mem_term_percent, args.swap_term_percent);
sig = SIGTERM;
}
if (sig) {
print_mem_stats(1, m);
userspace_kill(args, sig);
// With swap enabled, the kernel seems to need more than 100ms to free the memory
Expand Down
22 changes: 10 additions & 12 deletions msg.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

#include "msg.h"

// Print message to stderr and exit with "code".
// Print message, prefixed with "fatal: ", to stderr and exit with "code".
// Example: fatal(6, "could not compile regexp '%s'\n", regex_str);
void fatal(int code, char* fmt, ...)
{
Expand All @@ -28,7 +28,7 @@ void fatal(int code, char* fmt, ...)
exit(code);
}

// Print a yellow warning message to stderr.
// Print a yellow warning message to stderr. No "warning" prefix is added.
int warn(const char* fmt, ...)
{
int ret = 0;
Expand Down Expand Up @@ -84,11 +84,6 @@ term_kill_tuple_t parse_term_kill_tuple(char* optarg, long upper_limit)
"could not parse '%s'\n", optarg);
return tuple;
}
if (tuple.term == 0) {
snprintf(tuple.err, sizeof(tuple.err),
"zero SIGTERM value in '%s'\n", optarg);
return tuple;
}
if (tuple.term < 0) {
snprintf(tuple.err, sizeof(tuple.err),
"negative SIGTERM value in '%s'\n", optarg);
Expand All @@ -99,21 +94,24 @@ term_kill_tuple_t parse_term_kill_tuple(char* optarg, long upper_limit)
"SIGTERM value %ld exceeds limit %ld\n", tuple.term, upper_limit);
return tuple;
}
// User passed only "term" value
// User passed only the SIGTERM value: the SIGKILL value is calculated as
// SIGTERM/2.
if (n == 1) {
tuple.kill = tuple.term / 2;
return tuple;
}
// User passed "term,kill" values
if (tuple.kill < 0) {
snprintf(tuple.err, sizeof(tuple.err),
"negative SIGKILL value in '%s'\n", optarg);
return tuple;
}
if (tuple.kill > tuple.term) {
if (tuple.kill == 0 && tuple.term == 0) {
snprintf(tuple.err, sizeof(tuple.err),
"SIGKILL value exceeds SIGTERM value in '%s'\n", optarg);
"both SIGTERM and SIGKILL values are zero\n");
return tuple;
}
if (tuple.term > 0 && tuple.term < tuple.kill) {
warn("warning: SIGTERM value is non-zero but below SIGKILL, setting it to zero\n");
tuple.term = 0;
}
return tuple;
}
5 changes: 5 additions & 0 deletions tests/c_unit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ func TestParseTuple(t *testing.T) {
{arg: "220[,160]", limit: 300, shouldFail: true},
{arg: "180[,170]", limit: 300, shouldFail: true},
{arg: "5,0", limit: 100, term: 5, kill: 0},
{arg: "0,5", limit: 100, term: 0, kill: 5},
// SIGTERM value is set to zero when it is below SIGKILL
{arg: "4,5", limit: 100, term: 0, kill: 5},
{arg: "0", limit: 100, shouldFail: true},
{arg: "0,0", limit: 100, shouldFail: true},
}
for _, tc := range tcs {
err, term, kill := parse_term_kill_tuple(tc.arg, tc.limit)
Expand Down
6 changes: 2 additions & 4 deletions tests/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,13 +97,11 @@ func TestCli(t *testing.T) {
{args: []string{"-i", "1"}, code: 13, stderrContains: "extra argument not understood", stdoutEmpty: true},
// Tuples
{args: []string{"-m", "2,1"}, code: -1, stderrContains: "sending SIGTERM at 2 %, SIGKILL at 1 %", stdoutContains: memReport},
{args: []string{"-m", "1,2"}, code: 15, stderrContains: "fatal", stdoutEmpty: true},
{args: []string{"-m", "1,2"}, code: -1, stdoutContains: memReport},
{args: []string{"-m", "1,-1"}, code: 15, stderrContains: "fatal", stdoutEmpty: true},
{args: []string{"-m", "1000,-1000"}, code: 15, stderrContains: "fatal", stdoutEmpty: true},
{args: []string{"-s", "2,1"}, code: -1, stderrContains: "sending SIGTERM at 2 %, SIGKILL at 1 %", stdoutContains: memReport},
{args: []string{"-s", "1,2"}, code: 16, stderrContains: "fatal", stdoutEmpty: true},
// https://github.com/rfjakob/earlyoom/issues/97
{args: []string{"-s", "1,2"}, code: 16, stderrContains: "fatal", stdoutEmpty: true},
{args: []string{"-s", "1,2"}, code: -1, stdoutContains: memReport},
}
if swapTotal > 0 {
// Tests that cannot work when there is no swap enabled
Expand Down

0 comments on commit 28084c3

Please sign in to comment.