Skip to content

Commit

Permalink
Implement programmatic notifications
Browse files Browse the repository at this point in the history
Add support for running a script for each process killed (or would kill
in dryrun mode).

Signed-off-by: Nikos Tsipinakis <nikos.tsipinakis@cern.ch>
  • Loading branch information
tsipinakis authored and rfjakob committed Aug 4, 2021
1 parent 898f590 commit afe0360
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 2 deletions.
13 changes: 13 additions & 0 deletions MANPAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,19 @@ To actually see the notifications in your GUI session, you need to have
[systembus-notify](https://github.com/rfjakob/systembus-notify)
running as your user.

#### -N SCRIPT
Run the given script for each process killed.

Within the script, information about the killed process can be obtained via the
following environment variables:

EARLYOOM_PID Process PID
EARLYOOM_NAME Process name/path
EARLYOOM_UID UID of the user running the process

Warning: In case of dryrun mode, the script will be executed in rapid
succession, ensure you have some sort of rate-limit implemented.

#### -g
Kill all processes that have same process group id (PGID) as the process
with excessive memory usage.
Expand Down
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,13 @@ To actually see the notifications in your GUI session, you need to have
[systembus-notify](https://github.com/rfjakob/systembus-notify)
running as your user.

Additionally, earlyoom can execute a script for each process killed, providing
information about the process via the `EARLYOOM_PID`, `EARLYOOM_UID` and
`EARLYOOM_NAME` environment variables. Pass `-N /path/to/script` to enable.

Warning: In case of dryrun mode, the script will be executed in rapid
succession, ensure you have some sort of rate-limit implemented.

### Preferred Processes

The command-line flag `--prefer` specifies processes to prefer killing;
Expand Down
32 changes: 32 additions & 0 deletions kill.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
#define BADNESS_PREFER 300
#define BADNESS_AVOID -300

// Buffer size for UID/GID/PID string conversion
#define UID_BUFSIZ 128

static int isnumeric(char* str)
{
int i = 0;
Expand Down Expand Up @@ -61,6 +64,32 @@ static void notify(const char* summary, const char* body)
exit(1);
}

static void notify_ext(const char* script, const procinfo_t victim)
{
pid_t pid1 = fork();

if (pid1 == -1) {
warn("fork() returned -1: %s\n", strerror(errno));
return;
} else if (pid1 != 0) {
return;
}

char pid_str[UID_BUFSIZ];
char uid_str[UID_BUFSIZ];

snprintf(pid_str, UID_BUFSIZ, "%d", victim.pid);
snprintf(uid_str, UID_BUFSIZ, "%d", victim.uid);

setenv("EARLYOOM_PID", pid_str, 1);
setenv("EARLYOOM_UID", uid_str, 1);
setenv("EARLYOOM_NAME", victim.name, 1);

execlp(script, script, NULL);
warn("notify_ext: exec failed: %s\n", strerror(errno));
exit(1);
}

/*
* Send the selected signal to "pid" and wait for the process to exit
* (max 10 seconds)
Expand Down Expand Up @@ -312,6 +341,9 @@ void kill_process(const poll_loop_args_t* args, int sig, const procinfo_t victim
if (args->notify) {
notify("earlyoom", notif_args);
}
if (args->notify_ext) {
notify_ext(args->notify_ext, victim);
}
}

if (sig == 0) {
Expand Down
2 changes: 2 additions & 0 deletions kill.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ typedef struct {
double swap_kill_percent;
/* send d-bus notifications? */
bool notify;
/* Path to script for programmatic notifications (or NULL) */
char *notify_ext;
/* kill all processes within a process group */
bool kill_process_group;
/* prefer/avoid killing these processes. NULL = no-op. */
Expand Down
4 changes: 2 additions & 2 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,7 @@ int main(int argc, char* argv[])
args.kill_process_group = true;
break;
case 'N':
args.notify = true;
fprintf(stderr, "Notifying through D-Bus, argument '%s' ignored for compatability\n", optarg);
args.notify_ext = optarg;
break;
case 'd':
enable_debug = 1;
Expand Down Expand Up @@ -220,6 +219,7 @@ int main(int argc, char* argv[])
" -M SIZE[,KILL_SIZE] set available memory minimum to SIZE KiB\n"
" -S SIZE[,KILL_SIZE] set free swap minimum to SIZE KiB\n"
" -n enable d-bus notifications\n"
" -N enable programmatic notifications\n"
" -g kill all processes within a process group\n"
" -d enable debugging messages\n"
" -v print version information and exit\n"
Expand Down

0 comments on commit afe0360

Please sign in to comment.