chiark / gitweb /
kill: always send SIGCONT after SIGTERM
[elogind.git] / src / systemctl.c
index b33a89f63d76d9bd3ae05d28db2f5b35a75aca4d..2e8d10736702c6fc4380540dfec5522569d7df9b 100644 (file)
@@ -112,6 +112,7 @@ static enum dot {
 static bool private_bus = false;
 
 static pid_t pager_pid = 0;
+static pid_t agent_pid = 0;
 
 static int daemon_reload(DBusConnection *bus, char **args, unsigned n);
 static void pager_open(void);
@@ -132,7 +133,10 @@ static bool on_tty(void) {
 }
 
 static void spawn_ask_password_agent(void) {
-        pid_t parent, child;
+        pid_t parent;
+
+        if (agent_pid > 0)
+                return;
 
         /* We check STDIN here, not STDOUT, since this is about input,
          * not output */
@@ -150,16 +154,11 @@ static void spawn_ask_password_agent(void) {
         /* Spawns a temporary TTY agent, making sure it goes away when
          * we go away */
 
-        if ((child = fork()) < 0)
+        if ((agent_pid = fork()) < 0)
                 return;
 
-        if (child == 0) {
+        if (agent_pid == 0) {
                 /* In the child */
-                const char * const args[] = {
-                        SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH,
-                        "--watch",
-                        NULL
-                };
 
                 int fd;
                 bool stdout_is_tty, stderr_is_tty;
@@ -202,7 +201,9 @@ static void spawn_ask_password_agent(void) {
                                 close(fd);
                 }
 
-                execv(args[0], (char **) args);
+                execl(SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH, SYSTEMD_TTY_ASK_PASSWORD_AGENT_BINARY_PATH, "--watch", NULL);
+
+                log_error("Unable to execute agent: %m");
                 _exit(EXIT_FAILURE);
         }
 }
@@ -1420,6 +1421,7 @@ static int start_unit(DBusConnection *bus, char **args, unsigned n) {
                         streq(args[0], "condrestart")           ? "TryRestartUnit" :
                         streq(args[0], "reload-or-restart")     ? "ReloadOrRestartUnit" :
                         streq(args[0], "reload-or-try-restart") ||
+                        streq(args[0], "condreload") ||
                         streq(args[0], "force-reload")          ? "ReloadOrTryRestartUnit" :
                                                                   "StartUnit";
 
@@ -5165,6 +5167,7 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError
                 { "reload-or-restart",     MORE,  2, start_unit        },
                 { "reload-or-try-restart", MORE,  2, start_unit        },
                 { "force-reload",          MORE,  2, start_unit        }, /* For compatibility with SysV */
+                { "condreload",            MORE,  2, start_unit        }, /* For compatibility with ALTLinux */
                 { "condrestart",           MORE,  2, start_unit        }, /* For compatibility with RH */
                 { "isolate",               EQUAL, 2, start_unit        },
                 { "kill",                  MORE,  2, kill_unit         },
@@ -5447,6 +5450,7 @@ static int runlevel_main(void) {
 static void pager_open(void) {
         int fd[2];
         const char *pager;
+        pid_t parent_pid;
 
         if (pager_pid > 0)
                 return;
@@ -5467,6 +5471,8 @@ static void pager_open(void) {
                 return;
         }
 
+        parent_pid = getpid();
+
         pager_pid = fork();
         if (pager_pid < 0) {
                 log_error("Failed to fork pager: %m");
@@ -5482,7 +5488,14 @@ static void pager_open(void) {
 
                 setenv("LESS", "FRSX", 0);
 
-                prctl(PR_SET_PDEATHSIG, SIGTERM);
+                /* Make sure the pager goes away when the parent dies */
+                if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
+                        _exit(EXIT_FAILURE);
+
+                /* Check whether our parent died before we were able
+                 * to set the death signal */
+                if (getppid() != parent_pid)
+                        _exit(EXIT_SUCCESS);
 
                 if (pager) {
                         execlp(pager, pager, NULL);
@@ -5519,10 +5532,24 @@ static void pager_close(void) {
 
         /* Inform pager that we are done */
         fclose(stdout);
+        kill(pager_pid, SIGCONT);
         wait_for_terminate(pager_pid, &dummy);
         pager_pid = 0;
 }
 
+static void agent_close(void) {
+        siginfo_t dummy;
+
+        if (agent_pid <= 0)
+                return;
+
+        /* Inform agent that we are done */
+        kill(agent_pid, SIGTERM);
+        kill(agent_pid, SIGCONT);
+        wait_for_terminate(agent_pid, &dummy);
+        agent_pid = 0;
+}
+
 int main(int argc, char*argv[]) {
         int r, retval = EXIT_FAILURE;
         DBusConnection *bus = NULL;
@@ -5605,6 +5632,7 @@ finish:
         strv_free(arg_property);
 
         pager_close();
+        agent_close();
 
         return retval;
 }