Blob Blame History Raw
diff --git a/src/Debug.h b/src/Debug.h
index 6819d57..ccf2864 100644
--- a/src/Debug.h
+++ b/src/Debug.h
@@ -92,6 +92,9 @@ public:
     /// logs output buffer created in Start() and closes debugging context
     static void Finish();
 
+    /// prefixes each grouped debugs() line after the first one in the group
+    static std::ostream& Extra(std::ostream &os) { return os << "\n    "; }
+
 private:
     static Context *Current; ///< deepest active context; nil outside debugs()
 };
diff --git a/src/ipc.cc b/src/ipc.cc
index df638b0..9793949 100644
--- a/src/ipc.cc
+++ b/src/ipc.cc
@@ -19,6 +19,11 @@
 #include "SquidConfig.h"
 #include "SquidIpc.h"
 #include "tools.h"
+#include <cstdlib>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
 
 static const char *hello_string = "hi there\n";
 #define HELLO_BUF_SZ 32
@@ -333,6 +338,22 @@ ipcCreate(int type, const char *prog, const char *const args[], const char *name
     }
 
     PutEnvironment();
+
+    // A dup(2) wrapper that reports and exits the process on errors. The
+    // exiting logic is only suitable for this child process context.
+    const auto dupOrExit = [prog,name](const int oldFd) {
+        const auto newFd = dup(oldFd);
+        if (newFd < 0) {
+            const auto savedErrno = errno;
+            debugs(54, DBG_CRITICAL, "ERROR: Helper process initialization failure: " << name <<
+                   Debug::Extra << "helper (CHILD) PID: " << getpid() <<
+                   Debug::Extra << "helper program name: " << prog <<
+                   Debug::Extra << "dup(2) system call error for FD " << oldFd << ": " << xstrerr(savedErrno));
+            _exit(EXIT_FAILURE);
+        }
+        return newFd;
+    };
+
     /*
      * This double-dup stuff avoids problems when one of
      *  crfd, cwfd, or debug_log are in the rage 0-2.
@@ -340,17 +361,16 @@ ipcCreate(int type, const char *prog, const char *const args[], const char *name
 
     do {
         /* First make sure 0-2 is occupied by something. Gets cleaned up later */
-        x = dup(crfd);
-        assert(x > -1);
-    } while (x < 3 && x > -1);
+        x = dupOrExit(crfd);
+    } while (x < 3);
 
     close(x);
 
-    t1 = dup(crfd);
+    t1 = dupOrExit(crfd);
 
-    t2 = dup(cwfd);
+    t2 = dupOrExit(cwfd);
 
-    t3 = dup(fileno(debug_log));
+    t3 = dupOrExit(fileno(debug_log));
 
     assert(t1 > 2 && t2 > 2 && t3 > 2);