From 5a834f69b723cb4aa4ca9f7a23ad9b05f17cfb8f Mon Sep 17 00:00:00 2001 From: Art Cancro Date: Wed, 20 Dec 2006 19:04:43 +0000 Subject: [PATCH] * Lock citadel.control using flock() immediately after opening it. Failure to acquire a lock means that another citserver already running, which causes the server to abort. --- citadel/control.c | 20 +++++++++++++++++++- citadel/server_main.c | 4 ++++ citadel/sysdep.c | 17 ++++++++++++++++- 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/citadel/control.c b/citadel/control.c index f2268d8fa..0c9dd11b1 100644 --- a/citadel/control.c +++ b/citadel/control.c @@ -28,6 +28,7 @@ #include #include #include +#include #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), diff --git a/citadel/server_main.c b/citadel/server_main.c index ef1c9c96e..7c152d744 100644 --- a/citadel/server_main.c +++ b/citadel/server_main.c @@ -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. */ diff --git a/citadel/sysdep.c b/citadel/sysdep.c index f4e20d72e..c992adbe6 100644 --- a/citadel/sysdep.c +++ b/citadel/sysdep.c @@ -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); -- 2.39.2