shutdown: clean up error handling.
authorDavin McCall <davmac@davmac.org>
Mon, 5 Nov 2018 22:01:26 +0000 (22:01 +0000)
committerDavin McCall <davmac@davmac.org>
Mon, 5 Nov 2018 22:01:26 +0000 (22:01 +0000)
src/shutdown.cc

index 947896bef963d12e151d453a7b9208f7228578d9..d669d6b451d56e5146aa261b36067f4d8ceb1331 100644 (file)
@@ -1,10 +1,10 @@
 #include <cstddef>
 #include <cstdio>
 #include <csignal>
-#include <unistd.h>
 #include <cstring>
 #include <string>
 #include <iostream>
+#include <exception>
 
 #include <sys/reboot.h>
 #include <sys/types.h>
@@ -12,6 +12,7 @@
 #include <sys/un.h>
 #include <sys/wait.h>
 #include <sys/stat.h>
+#include <unistd.h>
 #include <fcntl.h>
 
 #include "cpbuffer.h"
@@ -536,46 +537,82 @@ static void run_process(const char * prog_args[], loop_t &loop, subproc_buffer &
     sp_watcher_t sp_watcher;
 
     // Create output pipe
+    bool have_pipe = true;
     int pipefds[2];
     if (dasynq::pipe2(pipefds, O_NONBLOCK) == -1) {
-        // TODO
-        std::cout << "*** pipe2 failed ***" << std::endl;
+        sub_buf.append("Warning: ");
+        sub_buf.append(prog_args[0]);
+        sub_buf.append(": could not create pipe for subprocess output\n");
+        have_pipe = false;
+        // Note, we proceed and let the sub-process run with our stdout/stderr.
     }
 
+    subproc_out_watch owatch {sub_buf};
+
+    if (have_pipe) {
+        close(pipefds[1]);
+        try {
+            owatch.add_watch(loop, pipefds[0], dasynq::IN_EVENTS);
+        }
+        catch (...) {
+            // failed to create the watcher for the subprocess output; again, let it run with
+            // our stdout/stderr
+            sub_buf.append("Warning: could not create output watch for subprocess\n");
+            close(pipefds[0]);
+            have_pipe = false;
+        }
+    }
+
+    // If we've buffered any messages/output, give them a chance to go out now:
+    loop.poll();
+
     pid_t ch_pid = sp_watcher.fork(loop);
     if (ch_pid == 0) {
         // child
         // Dup output pipe to stdout, stderr
-        dup2(pipefds[1], STDOUT_FILENO);
-        dup2(pipefds[1], STDERR_FILENO);
-        close(pipefds[0]);
-        close(pipefds[1]);
+        if (have_pipe) {
+            dup2(pipefds[1], STDOUT_FILENO);
+            dup2(pipefds[1], STDERR_FILENO);
+            close(pipefds[0]);
+            close(pipefds[1]);
+        }
         execv(prog_args[0], const_cast<char **>(prog_args));
-        puts("Failed to execute subprocess:\n");
+        puts("Failed to execute subprocess: ");
         perror(prog_args[0]);
         _exit(1);
     }
 
-    close(pipefds[1]);
-
-    subproc_out_watch owatch {sub_buf};
-    owatch.add_watch(loop, pipefds[0], dasynq::IN_EVENTS);
-
     do {
         loop.run();
     } while (! sp_watcher.terminated);
 
-    owatch.deregister(loop);
+    if (have_pipe) {
+        owatch.deregister(loop);
+    }
 }
 
 static void unmount_disks(loop_t &loop, subproc_buffer &sub_buf)
 {
-    const char * unmount_args[] = { "/bin/umount", "-a", "-r", nullptr };
-    run_process(unmount_args, loop, sub_buf);
+    try {
+        const char * unmount_args[] = { "/bin/umount", "-a", "-r", nullptr };
+        run_process(unmount_args, loop, sub_buf);
+    }
+    catch (std::exception &e) {
+        sub_buf.append("Couldn't fork for umount: ");
+        sub_buf.append(e.what());
+        sub_buf.append("\n");
+    }
 }
 
 static void swap_off(loop_t &loop, subproc_buffer &sub_buf)
 {
-    const char * swapoff_args[] = { "/sbin/swapoff", "-a", nullptr };
-    run_process(swapoff_args, loop, sub_buf);
+    try {
+        const char * swapoff_args[] = { "/sbin/swapoff", "-a", nullptr };
+        run_process(swapoff_args, loop, sub_buf);
+    }
+    catch (std::exception &e) {
+        sub_buf.append("Couldn't fork for swapoff: ");
+        sub_buf.append(e.what());
+        sub_buf.append("\n");
+    }
 }