https://issues.shibboleth.net/jira/browse/SSPCPP-204
authorScott Cantor <cantor.2@osu.edu>
Wed, 3 Jun 2009 17:29:09 +0000 (17:29 +0000)
committerScott Cantor <cantor.2@osu.edu>
Wed, 3 Jun 2009 17:29:09 +0000 (17:29 +0000)
shibd/shibd.cpp
shibsp/remoting/ListenerService.h
shibsp/remoting/impl/ListenerService.cpp
shibsp/remoting/impl/SocketListener.cpp
shibsp/remoting/impl/SocketListener.h

index 7331d75..122dc54 100644 (file)
@@ -143,10 +143,17 @@ int real_main(int preinit)
 \r
         if (!shar_checkonly) {\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
+            ListenerService* listener = conf.getServiceProvider()->getListenerService();\r
+            if (!listener->init(unlink_socket)) {\r
+                fprintf(stderr, "listener failed to initialize\n");\r
                 return -3;\r
             }\r
+            else if (!listener->run(&shibd_shutdown)) {\r
+                listener->term();\r
+                fprintf(stderr, "listener failed to begin service\n");\r
+                return -3;\r
+            }\r
+            listener->term();\r
         }\r
 \r
         conf.term();\r
@@ -170,6 +177,11 @@ static void run_handler(int arg)
     shibd_running = true;\r
 }\r
 \r
+static void child_handler(int arg)\r
+{\r
+    // Terminate the parent's wait/sleep if the newly born daemon dies early.\r
+}\r
+\r
 static int setup_signals(void)\r
 {\r
     struct sigaction sa;\r
@@ -205,6 +217,13 @@ static int setup_signals(void)
         if (sigaction(SIGUSR1, &sa, NULL) < 0) {\r
             return -1;\r
         }\r
+\r
+        memset(&sa, 0, sizeof (sa));\r
+        sa.sa_handler = child_handler;\r
+\r
+        if (sigaction(SIGCHLD, &sa, NULL) < 0) {\r
+            return -1;\r
+        }\r
     }\r
 \r
     return 0;\r
@@ -249,6 +268,7 @@ static int parse_args(int argc, char* argv[])
                 break;\r
             case 't':\r
                 shar_checkonly=true;\r
+                daemonize=false;\r
                 break;\r
             case 'v':\r
                 shar_version=true;\r
@@ -302,17 +322,31 @@ int main(int argc, char *argv[])
     if (daemonize) {\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
+        pid_t pid = fork();\r
+        switch (pid) {\r
+            case 0:\r
+                break;\r
+            case -1:\r
+                perror("forking");\r
+                exit(EXIT_FAILURE);\r
+            default:\r
+                sleep(daemon_wait);\r
+                if (shibd_running) {\r
+                    if (pidfile) {\r
+                        FILE* pidf = fopen(pidfile, "w");\r
+                        if (pidf) {\r
+                            fprintf(pidf, "%d\n", pid);\r
+                            fclose(pidf);\r
+                        }\r
+                        else {\r
+                            perror(pidfile);\r
+                        }\r
+                    }\r
+                    exit(EXIT_SUCCESS);\r
+                }\r
+                else {\r
                     exit(EXIT_FAILURE);\r
-                default:\r
-                    sleep(daemon_wait);\r
-                    exit(shibd_running ? EXIT_SUCCESS : EXIT_FAILURE);\r
-            }\r
+                }\r
         }\r
     }\r
 \r
@@ -336,32 +370,30 @@ int main(int argc, char *argv[])
             }\r
         }\r
 \r
-        // Write the pid file\r
-        if (pidfile) {\r
-            FILE* pidf = fopen(pidfile, "w");\r
-            if (pidf) {\r
-                fprintf(pidf, "%d\n", getpid());\r
-                fclose(pidf);\r
-            } else {\r
-                perror(pidfile);  // keep running though\r
-            }\r
-        }\r
-\r
         if (daemonize) {\r
             freopen("/dev/null", "r", stdin);\r
             freopen("/dev/null", "w", stdout);\r
             freopen("/dev/null", "w", stderr);\r
-            if (!conf.getServiceProvider()->getListenerService()->setSignal(SIGUSR1)) {\r
-                fprintf(stderr, "listener failed to accept signaling hook\n");\r
-                return -3;\r
-            }\r
         }\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
+        // Init the listener.\r
+        ListenerService* listener = conf.getServiceProvider()->getListenerService();\r
+        if (!listener->init(unlink_socket)) {\r
+            fprintf(stderr, "listener failed to initialize\n");\r
+            return -3;\r
+        }\r
+\r
+        // Signal our parent.\r
+        pid_t ppid = getppid();\r
+        kill(ppid, SIGUSR1);\r
+\r
+        // Run the listener.\r
+        if (!listener->run(&shibd_shutdown)) {\r
+            listener->term();\r
+            fprintf(stderr, "listener failed to begin service\n");\r
             return -3;\r
         }\r
+        listener->term();\r
     }\r
 \r
     conf.term();\r
index 62a2a4a..c85af8c 100644 (file)
@@ -115,21 +115,22 @@ 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.
+         * OutOfProcess servers can implement server-side initialization that should occur
+         * before daemonization.
          *
-         * @param s the signal to raise
-         * @return  true iff the signal was successfully installed
+         * <p>The parameter applies to implementations that can detect and remove
+         * the results of ungraceful shutdowns of previous executions and continue
+         * successfully. File-based sockets are the most common example.
+         *
+         * @param force     true iff remnant network state should be forcibly cleared
+         * @return true iff the service initialization was successful
          */
-        virtual bool setSignal(int s) {
-            return false;
+        virtual bool init(bool force) {
+            return true;
         }
-#endif
 
         /**
-         * @deprecated
          * OutOfProcess servers can implement server-side transport handling by
          * calling the run method and supplying a flag to monitor for shutdown.
          *
@@ -139,18 +140,10 @@ namespace shibsp {
         virtual bool run(bool* shutdown)=0;
 
         /**
-         * OutOfProcess servers can implement server-side transport handling by
-         * calling the run method and supplying a flag to monitor for shutdown.
-         *
-         * <p>The first parameter applies to implementations that can detect and remove
-         * the results of ungraceful shutdowns of previous executions and continue
-         * successfully. File-based sockets are the most common example.
-         *
-         * @param force     true iff remnant network state should be forcibly cleared
-         * @param shutdown  pointer to flag that caller will set when shutdown is required
-         * @return true iff the service execution was successful
+         * OutOfProcess servers can implement server-side termination/cleanup.
          */
-        virtual bool run(bool force, bool* shutdown);
+        virtual void term() {
+        }
 
     private:
         std::map<std::string,Remoted*> m_listenerMap;
index c85c356..f33b307 100644 (file)
@@ -96,8 +96,3 @@ void ListenerService::receive(DDF &in, ostream& out)
 
     dest->receive(in, out);
 }
-
-bool ListenerService::run(bool force, bool* shutdown)
-{
-    return run(shutdown);
-}
index 19056c0..8489546 100644 (file)
@@ -183,10 +183,10 @@ SocketListener::~SocketListener()
     delete m_child_lock;
 }
 
-bool SocketListener::run(bool force, bool* shutdown)
+bool SocketListener::init(bool force)
 {
 #ifdef _DEBUG
-    NDC ndc("run");
+    NDC ndc("init");
 #endif
     log->info("listener service starting");
 
@@ -199,10 +199,6 @@ bool SocketListener::run(bool force, bool* shutdown)
     }
     sp->unlock();
 
-    // Save flag to monitor for shutdown request.
-    m_shutdown=shutdown;
-    unsigned long count = 0;
-
     if (!create(m_socket)) {
         log->crit("failed to create socket");
         return false;
@@ -213,14 +209,17 @@ 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);
-    }
+    return true;
+}
+
+bool SocketListener::run(bool* shutdown)
+{
+#ifdef _DEBUG
+    NDC ndc("run");
 #endif
+    // Save flag to monitor for shutdown request.
+    m_shutdown=shutdown;
+    unsigned long count = 0;
 
     while (!*m_shutdown) {
         fd_set readfds;
@@ -238,7 +237,8 @@ bool SocketListener::run(bool force, bool* shutdown)
                 if (errno == EINTR) continue;
                 log_error();
                 log->error("select() on main listener socket failed");
-                return false;
+                *m_shutdown = true;
+                break;
 
             case 0:
                 continue;
@@ -275,9 +275,13 @@ bool SocketListener::run(bool force, bool* shutdown)
         m_child_wait->wait(m_child_lock);
     m_child_lock->unlock();
 
+    return true;
+}
+
+void SocketListener::term()
+{
     this->close(m_socket);
     m_socket=(ShibSocket)0;
-    return true;
 }
 
 DDF SocketListener::send(const DDF& in)
index f555e4d..a558650 100644 (file)
@@ -54,17 +54,9 @@ namespace shibsp {
 
         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);
-        }
-        bool run(bool force, bool* shutdown);
+        bool init(bool force);
+        bool run(bool* shutdown);
+        void term();
 
         // Implemented by socket-specific subclasses.
 #ifdef WIN32
@@ -88,9 +80,6 @@ namespace shibsp {
 
     private:
         mutable SocketPool* m_socketpool;
-#ifndef WIN32
-        int m_signal;
-#endif
         bool* m_shutdown;
 
         // Manage child threads