* Lock citadel.control using flock() immediately after
authorArt Cancro <ajc@citadel.org>
Wed, 20 Dec 2006 19:04:43 +0000 (19:04 +0000)
committerArt Cancro <ajc@citadel.org>
Wed, 20 Dec 2006 19:04:43 +0000 (19:04 +0000)
  opening it.  Failure to acquire a lock means that another citserver
  already running, which causes the server to abort.

citadel/control.c
citadel/server_main.c
citadel/sysdep.c

index f2268d8fa2f06c655e71ea313675a8992d2c5efa..0c9dd11b13b8f815fe2b1932d7168712cd5df526 100644 (file)
@@ -28,6 +28,7 @@
 #include <errno.h>
 #include <limits.h>
 #include <sys/types.h>
+#include <sys/file.h>
 #include "citadel.h"
 #include "server.h"
 #include "control.h"
@@ -48,12 +49,27 @@ struct CitControl CitControl;
 extern struct config config;
 FILE *control_fp = NULL;
 
+
+
+/*
+ * lock_control  -  acquire a lock on the control record file.
+ *                  This keeps multiple citservers from running concurrently.
+ */
+void lock_control(void)
+{
+       if (flock(fileno(control_fp), (LOCK_EX | LOCK_NB))) {
+               lprintf(CTDL_EMERG, "citserver: unable to lock %s.\n", file_citadel_control);
+               lprintf(CTDL_EMERG, "Is another citserver already running?\n");
+               exit(1);
+       }
+}
+
+
 /*
  * get_control  -  read the control record into memory.
  */
 void get_control(void)
 {
-
        /* Zero it out.  If the control record on disk is missing or short,
         * the system functions with all control record fields initialized
         * to zero.
@@ -62,12 +78,14 @@ void get_control(void)
        if (control_fp == NULL) {
                control_fp = fopen(file_citadel_control, "rb+");
                if (control_fp != NULL) {
+                       lock_control();
                        fchown(fileno(control_fp), config.c_ctdluid, -1);
                }
        }
        if (control_fp == NULL) {
                control_fp = fopen(file_citadel_control, "wb+");
                if (control_fp != NULL) {
+                       lock_control();
                        fchown(fileno(control_fp), config.c_ctdluid, -1);
                        memset(&CitControl, 0, sizeof(struct CitControl));
                        fwrite(&CitControl, sizeof(struct CitControl),
index ef1c9c96efb3c1be1e45a4ae16d87f110c373df5..7c152d74439a047b3ca6b7b8bbdbe91ffd9a5900 100644 (file)
@@ -51,6 +51,7 @@
 #include "citserver.h"
 #include "support.h"
 #include "config.h"
+#include "control.h"
 #include "database.h"
 #include "housekeeping.h"
 #include "tools.h"
@@ -187,6 +188,9 @@ int main(int argc, char **argv)
        config.c_ipgm_secret = rand();
        put_config();
 
+       lprintf(CTDL_INFO, "Acquiring control record\n");
+       get_control();
+
 #ifdef HAVE_RUN_DIR
        /* on some dists rundir gets purged on startup. so we need to recreate it. */
 
index f4e20d72ebb3c6bda71acff9ecad6fce5d95f1e9..c992adbe6f6b57a51a89c7cca953a09a807f05ce 100644 (file)
@@ -757,7 +757,22 @@ void kill_session(int session_to_kill) {
  * Start running as a daemon.
  */
 void start_daemon(int unused) {
-       close(0); close(1); close(2);
+       int nullfd;
+
+       /* Close stdin/stdout/stderr and replace them with /dev/null.
+        * We don't just call close() because we don't want these fd's
+        * to be reused for other files.
+        */
+       nullfd = open("/dev/null", O_RDWR);
+       if (nullfd < 0) {
+               fprintf(stderr, "/dev/null: %s\n", strerror(errno));
+               exit(2);
+       }
+       dup2(nullfd, 0);
+       dup2(nullfd, 1);
+       dup2(nullfd, 2);
+       close(nullfd);
+
        if (fork()) exit(0);
        setsid();
        signal(SIGHUP,SIG_IGN);