https://issues.shibboleth.net/jira/browse/SSPCPP-204
authorScott Cantor <cantor.2@osu.edu>
Thu, 21 May 2009 16:40:27 +0000 (16:40 +0000)
committerScott Cantor <cantor.2@osu.edu>
Thu, 21 May 2009 16:40:27 +0000 (16:40 +0000)
.cproject
shibd/shibd.cpp
shibsp/remoting/ListenerService.h
shibsp/remoting/impl/SocketListener.cpp
shibsp/remoting/impl/SocketListener.h

index 374c971..13ce7f4 100644 (file)
--- a/.cproject
+++ b/.cproject
@@ -26,6 +26,8 @@
 <pathentry base-path="cpp-sp" include="shibsp" kind="inc" path="" system="true"/>\r
 <pathentry base-path="cpp-sp" include="" kind="inc" path="" system="true"/>\r
 <pathentry kind="mac" name="SHIBSP_API" path="" value=""/>\r
+<pathentry kind="mac" name="WIN32" path="" value=""/>\r
+<pathentry kind="mac" name="_MSC_VER" path="" value=""/>\r
 <pathentry kind="out" path=""/>\r
 <pathentry excluding="util/|impl/|security/|metadata/|remoting/|remoting/impl/|attribute/|binding/|binding/impl/|attribute/resolver/|attribute/resolver/impl/|handler/|handler/impl/|attribute/filtering/|attribute/filtering/impl/|lite/" kind="src" path="shibsp"/>\r
 <pathentry excluding="resolver/|resolver/impl/|filtering/|filtering/impl/" kind="src" path="shibsp/attribute"/>\r
index 5d18ec1..c5f5ba6 100644 (file)
@@ -156,11 +156,19 @@ int real_main(int preinit)
 \r
 #else\r
 \r
+int daemon_wait = 3;\r
+bool shibd_running = false;\r
+\r
 static void term_handler(int arg)\r
 {\r
     shibd_shutdown = true;\r
 }\r
 \r
+static void run_handler(int arg)\r
+{\r
+    shibd_running = true;\r
+}\r
+\r
 static int setup_signals(void)\r
 {\r
     struct sigaction sa;\r
@@ -188,6 +196,14 @@ static int setup_signals(void)
     if (sigaction(SIGTERM, &sa, NULL) < 0) {\r
         return -1;\r
     }\r
+\r
+    memset(&sa, 0, sizeof (sa));\r
+    sa.sa_handler = run_handler;\r
+\r
+    if (sigaction(SIGUSR1, &sa, NULL) < 0) {\r
+        return -1;\r
+    }\r
+\r
     return 0;\r
 }\r
 \r
@@ -200,6 +216,7 @@ static void usage(char* whoami)
     fprintf(stderr, "  -t\tcheck configuration file for problems.\n");\r
     fprintf(stderr, "  -f\tforce removal of listener socket.\n");\r
     fprintf(stderr, "  -p\tpid file to use.\n");\r
+    fprintf(stderr, "  -w\tseconds to wait for successful daemonization.\n");\r
     fprintf(stderr, "  -v\tprint software version.\n");\r
     fprintf(stderr, "  -h\tprint this help message.\n");\r
     exit(1);\r
@@ -209,7 +226,7 @@ static int parse_args(int argc, char* argv[])
 {\r
     int opt;\r
 \r
-    while ((opt = getopt(argc, argv, "d:c:x:p:ftvh")) > 0) {\r
+    while ((opt = getopt(argc, argv, "d:c:x:p:w:ftvh")) > 0) {\r
         switch (opt) {\r
             case 'd':\r
                 shar_prefix=optarg;\r
@@ -232,6 +249,12 @@ static int parse_args(int argc, char* argv[])
             case 'p':\r
                 pidfile=optarg;\r
                 break;\r
+            case 'w':\r
+                if (optarg)\r
+                    daemon_wait = atoi(optarg);\r
+                if (daemon_wait <= 0)\r
+                    daemon_wait = 3;\r
+                break;\r
             default:\r
                 return -1;\r
         }\r
@@ -269,6 +292,21 @@ int main(int argc, char *argv[])
         return -1;\r
     }\r
 \r
+    // We must fork() early, while we're single threaded.\r
+    // StorageService cleanup thread is about to start.\r
+    if (!shar_checkonly) {\r
+        switch (fork()) {\r
+            case 0:\r
+                break;\r
+            case -1:\r
+                perror("forking");\r
+                exit(EXIT_FAILURE);\r
+            default:\r
+                sleep(daemon_wait);\r
+                exit(shibd_running ? EXIT_SUCCESS : EXIT_FAILURE);\r
+        }\r
+    }\r
+\r
     if (!conf.instantiate(shar_config)) {\r
         fprintf(stderr, "configuration is invalid, check console for specific problems\n");\r
         conf.term();\r
@@ -278,6 +316,15 @@ int main(int argc, char *argv[])
     if (shar_checkonly)\r
         fprintf(stderr, "overall configuration is loadable, check console for non-fatal problems\n");\r
     else {\r
+        if (setsid() == -1) {\r
+            perror("setsid");\r
+            exit(EXIT_FAILURE);\r
+        }\r
+        if (chdir("/") == -1) {\r
+            perror("chdir to root");\r
+            exit(EXIT_FAILURE);\r
+        }\r
+\r
         // Write the pid file\r
         if (pidfile) {\r
             FILE* pidf = fopen(pidfile, "w");\r
@@ -289,6 +336,10 @@ int main(int argc, char *argv[])
             }\r
         }\r
 \r
+        freopen("/dev/null", "r", stdin);\r
+        freopen("/dev/null", "w", stdout);\r
+        freopen("/dev/null", "w", stderr);\r
+\r
         // Run the listener\r
         if (!conf.getServiceProvider()->getListenerService()->run(unlink_socket, &shibd_shutdown)) {\r
             fprintf(stderr, "listener failed to enter listen loop\n");\r
index 8bde279..62a2a4a 100644 (file)
@@ -115,6 +115,19 @@ namespace shibsp {
          */
         virtual Remoted* lookup(const char* address) const;
 
+#ifndef WIN32
+        /**
+         * Installs a signal that the service should raise to its parent process
+         * before entering a running state.
+         *
+         * @param s the signal to raise
+         * @return  true iff the signal was successfully installed
+         */
+        virtual bool setSignal(int s) {
+            return false;
+        }
+#endif
+
         /**
          * @deprecated
          * OutOfProcess servers can implement server-side transport handling by
index 848ed29..19056c0 100644 (file)
@@ -158,8 +158,12 @@ void SocketPool::put(SocketListener::ShibSocket s)
     m_lock->unlock();
 }
 
-SocketListener::SocketListener(const DOMElement* e) : m_catchAll(false), log(&Category::getInstance(SHIBSP_LOGCAT".Listener")),
-    m_socketpool(NULL), m_shutdown(NULL), m_child_lock(NULL), m_child_wait(NULL), m_socket((ShibSocket)0)
+SocketListener::SocketListener(const DOMElement* e)
+    : m_catchAll(false), log(&Category::getInstance(SHIBSP_LOGCAT".Listener")), m_socketpool(NULL),
+#ifndef WIN32
+        m_signal(0),
+#endif
+        m_shutdown(NULL), m_child_lock(NULL), m_child_wait(NULL), m_socket((ShibSocket)0)
 {
     // Are we a client?
     if (SPConfig::getConfig().isEnabled(SPConfig::InProcess)) {
@@ -209,6 +213,15 @@ bool SocketListener::run(bool force, bool* shutdown)
         return false;
     }
 
+#ifndef WIN32
+    if (m_signal) {
+        // Notify our parent that we're entering the select loop.
+        pid_t ppid = getppid();
+        kill(ppid, SIGUSR1);
+        log->info("notified parent (%d) upon entering select loop", ppid);
+    }
+#endif
+
     while (!*m_shutdown) {
         fd_set readfds;
         FD_ZERO(&readfds);
index 4439927..f555e4d 100644 (file)
@@ -53,6 +53,14 @@ namespace shibsp {
         ~SocketListener();
 
         DDF send(const DDF& in);
+
+#ifndef WIN32
+        bool setSignal(int s) {
+            m_signal = s;
+            return true;
+        }
+#endif
+
         bool run(bool* shutdown) {
             return run(true, shutdown);
         }
@@ -80,6 +88,9 @@ namespace shibsp {
 
     private:
         mutable SocketPool* m_socketpool;
+#ifndef WIN32
+        int m_signal;
+#endif
         bool* m_shutdown;
 
         // Manage child threads