@@ -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-
8562static int
8663pidfd_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+
164176static 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
198211static 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