Simple concurrency lock to prevent multiple citservers running at the same time
authorArt Cancro <ajc@citadel.org>
Sat, 10 Sep 2016 21:20:21 +0000 (17:20 -0400)
committerArt Cancro <ajc@citadel.org>
Sat, 10 Sep 2016 21:20:21 +0000 (17:20 -0400)
citadel/citserver.c
citadel/citserver.h
citadel/database.c
citadel/server_main.c

index 9f41f35f56bc9d55ee2e9827cae596631bc99f63..f389ac9f020b303551e62769d12c4d9135ea9b6c 100644 (file)
@@ -185,9 +185,9 @@ void master_startup(void) {
 
 
 /*
- * Cleanup routine to be called when the server is shutting down.
+ * Cleanup routine to be called when the server is shutting down.  Returns the needed exit code.
  */
-void master_cleanup(int exitcode) {
+int master_cleanup(int exitcode) {
        struct CleanupFunctionHook *fcn;
        static int already_cleaning_up = 0;
 
@@ -225,11 +225,13 @@ void master_cleanup(int exitcode) {
        syslog(LOG_NOTICE, "citserver: Exiting with status %d\n", exitcode);
        fflush(stdout); fflush(stderr);
        
-       if (restart_server != 0)
-               exit(1);
-       if ((running_as_daemon != 0) && ((exitcode == 0) ))
+       if (restart_server != 0) {
+               exitcode = 1;
+       }
+       else if ((running_as_daemon != 0) && ((exitcode == 0) )) {
                exitcode = CTDLEXIT_SHUTDOWN;
-       exit(exitcode);
+       }
+       return(exitcode);
 }
 
 
index c0249251201cf4a08722ac5e3d0d32e16ff10e72..61f1964b7b4c609b70ba2fc6458c5f5b909d5f0f 100644 (file)
@@ -36,7 +36,7 @@ void cit_backtrace(void);
 void cit_oneline_backtrace(void);
 void cit_panic_backtrace(int SigNum);
 void master_startup (void);
-void master_cleanup (int exitcode);
+int master_cleanup (int exitcode);
 void set_wtmpsupp (char *newtext);
 void set_wtmpsupp_to_current_room(void);
 void do_command_loop(void);
index e7e57a6437e38c712443bea4ab76b4e4626a4166..dbfac8dd54ebc1522ea588b2d87c483457183794 100644 (file)
 #ifdef HAVE_DB_H
 #include <db.h>
 #elif defined(HAVE_DB4_DB_H)
-#include <db4/db.h>
+#include <db5/db.h>
 #else
-#error Neither <db.h> nor <db4/db.h> was found by configure. Install db4-devel.
+#error Neither <db.h> nor <db5/db.h> was found by configure. Install db5-devel.
 #endif
 
-
-#if DB_VERSION_MAJOR < 4 || DB_VERSION_MINOR < 1
-#error Citadel requires Berkeley DB v4.1 or newer.  Please upgrade.
+#if DB_VERSION_MAJOR < 5
+#error Citadel requires Berkeley DB v5.0 or newer.  Please upgrade.
 #endif
 
-
 #include <libcitadel.h>
 
 #include "ctdl_module.h"
@@ -52,7 +50,6 @@
 #include "citserver.h"
 #include "config.h"
 
-
 static DB *dbp[MAXCDB];                /* One DB handle for each Citadel database */
 static DB_ENV *dbenv;          /* The DB environment (global) */
 
@@ -281,9 +278,7 @@ void open_databases(void)
        dbenv->set_paniccall(dbenv, dbpanic);
        dbenv->set_errcall(dbenv, cdb_verbose_err);
        dbenv->set_errpfx(dbenv, "ctdl");
-#if (DB_VERSION_MAJOR > 4) || ( (DB_VERSION_MAJOR == 4) && (DB_VERSION_MINOR >= 3) )
        dbenv->set_msgcall(dbenv, cdb_verbose_log);
-#endif
        dbenv->set_verbose(dbenv, DB_VERB_DEADLOCK, 1);
        dbenv->set_verbose(dbenv, DB_VERB_RECOVERY, 1);
 
index 45312588ee614e90f17c836fd2b05e95f7c5578c..061273a6336c034c2357039bf40ad3db4802a952 100644 (file)
@@ -14,6 +14,7 @@
 #include <stdio.h>
 #include <sys/types.h>
 #include <grp.h>
+#include <sys/file.h>
 #include <libcitadel.h>
 
 #include "citserver.h"
@@ -34,6 +35,42 @@ const char *CitadelServiceTCP="citadel-TCP";
 
 void go_threading(void);
 
+
+
+/*
+ * Create or remove a lock file, so we only have one Citadel Server running at a time.
+ */
+void ctdl_lockfile(int yo) {
+       static char lockfilename[SIZ];
+       static FILE *fp;
+
+
+       if (yo) {
+               syslog(LOG_DEBUG, "Creating lockfile");
+               snprintf(lockfilename, sizeof lockfilename, "%s/citadel.lock", ctdl_run_dir);
+               fp = fopen(lockfilename, "w");
+               if (!fp) {
+                       syslog(LOG_ERR, "Cannot open or create %s", lockfilename);
+                       exit(CTDLEXIT_DB);
+               }
+               if (flock(fileno(fp), (LOCK_EX|LOCK_NB)) != 0) {
+                       syslog(LOG_ERR, "Cannot lock %s , is another citserver running?", lockfilename);
+                       exit(CTDLEXIT_DB);
+               }
+               return;
+       }
+
+       syslog(LOG_DEBUG, "Removing lockfile");
+       unlink(lockfilename);
+       flock(fileno(fp), LOCK_UN);
+       fclose(fp);
+}
+
+
+
+
+
+
 /*
  * Here's where it all begins.
  */
@@ -232,6 +269,8 @@ int main(int argc, char **argv)
 
 #endif
 
+       ctdl_lockfile(1);
+
        /* Initialize... */
        init_sysdep();
 
@@ -362,6 +401,7 @@ int main(int argc, char **argv)
 
        go_threading();
        
-       master_cleanup(exit_signal);
-       return(0);
+       int exit_code = master_cleanup(exit_signal);
+       ctdl_lockfile(0);
+       return(exit_code);
 }