Skip to content

Commit 3b1a679

Browse files
committed
Introduce notify_spawn_subprocess helper
Gets rid of the separate (and buggy! does not handle fork failure) notify_dbus forking.
1 parent 8913fb2 commit 3b1a679

File tree

1 file changed

+57
-41
lines changed

1 file changed

+57
-41
lines changed

kill.c

Lines changed: 57 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -59,36 +59,13 @@ static bool isnumeric(char* str)
5959
}
6060
}
6161

62-
static void notify_dbus(const char* summary, const char* body)
63-
{
64-
int pid = fork();
65-
if (pid > 0) {
66-
// parent
67-
return;
68-
}
69-
char summary2[1024] = { 0 };
70-
snprintf(summary2, sizeof(summary2), "string:%s", summary);
71-
char body2[1024] = "string:";
72-
if (body != NULL) {
73-
snprintf(body2, sizeof(body2), "string:%s", body);
74-
}
75-
const char* dbus_send_path = "/usr/bin/dbus-send";
76-
debug("%s: exec %s\n", __func__, dbus_send_path);
77-
// Complete command line looks like this:
78-
// dbus-send --system / net.nuetzlich.SystemNotifications.Notify 'string:summary text' 'string:and body text'
79-
execl(dbus_send_path, "dbus-send", "--system", "/", "net.nuetzlich.SystemNotifications.Notify",
80-
summary2, body2, NULL);
81-
warn("%s: exec failed: %s\n", __func__, strerror(errno));
82-
exit(1);
83-
}
84-
8562
static int
8663
pidfd_open(pid_t pid, unsigned int flags)
8764
{
8865
return (int)syscall(SYS_pidfd_open, pid, flags);
8966
}
9067

91-
static void notify_ext(const char* script, const procinfo_t* victim, int timeout_ms)
68+
static void notify_spawn_subprocess(const char* script, char* const argv[], const procinfo_t* victim, int timeout_ms)
9269
{
9370
// Prevent our SIGCHLD handler from reaping
9471
// children before we can
@@ -144,23 +121,58 @@ static void notify_ext(const char* script, const procinfo_t* victim, int timeout
144121
// we are the child
145122
sigprocmask(SIG_UNBLOCK, &set, NULL);
146123

147-
char pid_str[UID_BUFSIZ] = { 0 };
148-
char uid_str[UID_BUFSIZ] = { 0 };
124+
if (victim) {
125+
char pid_str[UID_BUFSIZ] = { 0 };
126+
char uid_str[UID_BUFSIZ] = { 0 };
149127

150-
snprintf(pid_str, UID_BUFSIZ, "%d", victim->pid);
151-
snprintf(uid_str, UID_BUFSIZ, "%d", victim->uid);
128+
snprintf(pid_str, UID_BUFSIZ, "%d", victim->pid);
129+
snprintf(uid_str, UID_BUFSIZ, "%d", victim->uid);
152130

153-
setenv("EARLYOOM_PID", pid_str, 1);
154-
setenv("EARLYOOM_UID", uid_str, 1);
155-
setenv("EARLYOOM_NAME", victim->name, 1);
156-
setenv("EARLYOOM_CMDLINE", victim->cmdline, 1);
131+
setenv("EARLYOOM_PID", pid_str, 1);
132+
setenv("EARLYOOM_UID", uid_str, 1);
133+
setenv("EARLYOOM_NAME", victim->name, 1);
134+
setenv("EARLYOOM_CMDLINE", victim->cmdline, 1);
135+
}
157136

158137
debug("%s: exec %s\n", __func__, script);
159-
execl(script, script, NULL);
138+
execv(script, argv);
160139
warn("%s: exec %s failed: %s\n", __func__, script, strerror(errno));
161140
exit(1);
162141
}
163142

143+
// "-n" option
144+
static void notify_dbus(const char* body)
145+
{
146+
char body2[1024] = "string:";
147+
if (body != NULL) {
148+
snprintf(body2, sizeof(body2), "string:%s", body);
149+
}
150+
151+
// Complete command line looks like this:
152+
// dbus-send --system / net.nuetzlich.SystemNotifications.Notify 'string:earlyoom' 'string:and body text'
153+
char* const argv[] = {
154+
"dbus-send",
155+
"--system",
156+
"/",
157+
"net.nuetzlich.SystemNotifications.Notify",
158+
"string:earlyoom",
159+
body2,
160+
NULL
161+
};
162+
const char* dbus_send_path = "/usr/bin/dbus-send";
163+
notify_spawn_subprocess(dbus_send_path, argv, NULL, 0);
164+
}
165+
166+
// "-N" option
167+
static void notify_ext(char* const script, const procinfo_t* victim)
168+
{
169+
char* const argv[] = {
170+
script,
171+
NULL
172+
};
173+
notify_spawn_subprocess(script, argv, victim, 0);
174+
}
175+
164176
static void notify_process_killed(const poll_loop_args_t* args, const procinfo_t* victim)
165177
{
166178
// Dry run can cause the notify function to be called on each poll as
@@ -188,20 +200,24 @@ static void notify_process_killed(const poll_loop_args_t* args, const procinfo_t
188200
char notif_args[PATH_MAX + 1000];
189201
snprintf(notif_args, sizeof(notif_args),
190202
"Low memory! Killing process %d %s", victim->pid, victim->name);
191-
notify_dbus("earlyoom", notif_args);
203+
notify_dbus(notif_args);
192204
}
193205
if (args->notify_ext) {
194-
notify_ext(args->notify_ext, victim, 0);
206+
notify_ext(args->notify_ext, victim);
195207
}
196208
}
197209

210+
// "-P" option
198211
static void kill_process_prehook(const poll_loop_args_t* args, const procinfo_t* victim)
199212
{
200-
if (args->kill_process_prehook) {
201-
// reuse notify_ext() to invoke, functionally it's the same as invoking
202-
// for notification
203-
notify_ext(args->kill_process_prehook, victim, PREHOOK_STARTUP_SLEEP_MS);
213+
if (!args->kill_process_prehook) {
214+
return;
204215
}
216+
char* const argv[] = {
217+
args->kill_process_prehook,
218+
NULL,
219+
};
220+
notify_spawn_subprocess(args->kill_process_prehook, argv, victim, PREHOOK_STARTUP_SLEEP_MS);
205221
}
206222

207223
#if defined(__NR_pidfd_open) && defined(__NR_process_mrelease)
@@ -589,7 +605,7 @@ void kill_process(const poll_loop_args_t* args, int sig, const procinfo_t* victi
589605
if (victim->pid <= 0) {
590606
warn("Could not find a process to kill. Sleeping 1 second.\n");
591607
if (args->notify) {
592-
notify_dbus("earlyoom", "Error: Could not find a process to kill. Sleeping 1 second.");
608+
notify_dbus("Error: Could not find a process to kill. Sleeping 1 second.");
593609
}
594610
sleep(1);
595611
return;
@@ -634,7 +650,7 @@ void kill_process(const poll_loop_args_t* args, int sig, const procinfo_t* victi
634650
if (res != 0) {
635651
warn("kill failed: %s\n", strerror(saved_errno));
636652
if (args->notify) {
637-
notify_dbus("earlyoom", "Error: Failed to kill process");
653+
notify_dbus("Error: Failed to kill process");
638654
}
639655
// Killing the process may have failed because we are not running as root.
640656
// In that case, trying again in 100ms will just yield the same error.

0 commit comments

Comments
 (0)