]> git.tuebingen.mpg.de Git - paraslash.git/blobdiff - server.c
server: Exit cleanly on SIGINT/SIGTERM.
[paraslash.git] / server.c
index 4f1d5708f76e997ff8fc5ee477dd97d65a6b3785..13c8c85f98339023b90415125e9df275a28c98f3 100644 (file)
--- a/server.c
+++ b/server.c
@@ -106,6 +106,24 @@ static struct signal_task *signal_task;
 /** The process id of the audio file selector process. */
 pid_t afs_pid = 0;
 
+/* The the main server process (parent of afs and the command handlers). */
+static pid_t server_pid;
+
+/**
+ * Tell whether the executing process is a command handler.
+ *
+ * Cleanup on exit must be performed differently for command handlers.
+ *
+ * \return True if the pid of the executing process is neither the server pid
+ * nor the afs pid.
+ */
+bool process_is_command_handler(void)
+{
+       pid_t pid = getpid();
+
+       return pid != afs_pid && pid != server_pid;
+}
+
 /** The task responsible for server command handling. */
 struct server_command_task {
        /** TCP port on which para_server listens for connections. */
@@ -307,27 +325,22 @@ static int signal_post_select(struct sched *s, __a_unused void *context)
                PARA_EMERG_LOG("terminating on signal %d\n", signum);
                kill(0, SIGTERM);
                /*
-                * We must wait for afs because afs catches SIGINT/SIGTERM.
-                * Before reacting to the signal, afs might want to use the
+                * We must wait for all of our children to die. For the afs
+                * process or a command handler might want to use the
                 * shared memory area and the mmd mutex.  If we destroy this
                 * mutex too early and afs tries to lock the shared memory
                 * area, the call to mutex_lock() will fail and terminate the
                 * afs process. This leads to dirty osl tables.
-                *
-                * There's no such problem with the other children of the
-                * server process (the command handlers) as these reset their
-                * SIGINT/SIGTERM handlers to the default action, i.e.  these
-                * processes get killed immediately by the above kill().
                 */
-               PARA_INFO_LOG("waiting for afs (pid %d) to die\n",
-                       (int)afs_pid);
-               waitpid(afs_pid, NULL, 0);
+               PARA_INFO_LOG("waiting for child processes to die\n");
+               mutex_unlock(mmd_mutex);
+               while (wait(NULL) != -1 || errno != ECHILD)
+                       ; /* still at least one child alive */
+               mutex_lock(mmd_mutex);
 cleanup:
                free(mmd->afd.afhi.chunk_table);
-               close_listed_fds();
-               mutex_destroy(mmd_mutex);
-               shm_detach(mmd);
-               exit(EXIT_FAILURE);
+               task_notify_all(s, E_DEADLY_SIGNAL);
+               return -E_DEADLY_SIGNAL;
        }
        return 0;
 }
@@ -532,6 +545,7 @@ static void server_init(int argc, char **argv, struct server_command_task *sct)
        /* become daemon */
        if (OPT_GIVEN(DAEMON))
                daemon_pipe = daemonize(true /* parent waits for SIGTERM */);
+       server_pid = getpid();
        init_random_seed_or_die();
        daemon_log_welcome("server");
        init_ipc_or_die(); /* init mmd struct and mmd->lock */
@@ -630,21 +644,25 @@ int main(int argc, char *argv[])
        server_init(argc, argv, sct);
        mutex_lock(mmd_mutex);
        ret = schedule(&sched);
+       /*
+        * We hold the mmd lock: it was re-acquired in server_select()
+        * after the select call.
+        */
+       mutex_unlock(mmd_mutex);
        sched_shutdown(&sched);
        signal_shutdown(signal_task);
-       if (sct->child_fd < 0) { /* parent (server) */
+       if (!process_is_command_handler()) { /* parent (server) */
+               mutex_destroy(mmd_mutex);
+               shm_detach(mmd);
                if (ret < 0)
                        PARA_EMERG_LOG("%s\n", para_strerror(-ret));
-       } else { /* child (command handler) */
-               /*
-                * We hold the lock: it was re-acquired in server_select()
-                * after the select call.
-                */
-               mutex_unlock(mmd_mutex);
+       } else {
                alarm(ALARM_TIMEOUT);
                close_listed_fds();
                ret = handle_connect(sct->child_fd);
        }
+       vss_shutdown();
+       shm_detach(mmd);
        lls_free_parse_result(server_lpr, CMD_PTR);
        if (server_lpr != cmdline_lpr)
                lls_free_parse_result(cmdline_lpr, CMD_PTR);