From 1b63fa550329a10571aaaefd94f52f72111715ec Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Sat, 8 Dec 2007 03:41:00 +0000 Subject: [PATCH] use file locks to keep multiple concurrent copies of freeswitch from running at the same time (FSCORE-14) git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@6575 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- src/include/switch_apr.h | 25 +++++++++++++++++++++ src/switch.c | 48 +++++++++++++++++++++++++++++++--------- src/switch_apr.c | 5 +++++ 3 files changed, 67 insertions(+), 11 deletions(-) diff --git a/src/include/switch_apr.h b/src/include/switch_apr.h index e7e639b3d6..2239f12149 100644 --- a/src/include/switch_apr.h +++ b/src/include/switch_apr.h @@ -644,6 +644,29 @@ SWITCH_DECLARE(switch_status_t) switch_queue_trypush(switch_queue_t * queue, voi #define SWITCH_FPROT_FILE_SOURCE_PERMS 0x1000 /**< Copy source file's permissions */ /** @} */ +/* File lock types/flags */ +/** + * @defgroup switch_file_lock_types File Lock Types + * @{ + */ + +#define SWITCH_FLOCK_SHARED 1 /**< Shared lock. More than one process + or thread can hold a shared lock + at any given time. Essentially, + this is a "read lock", preventing + writers from establishing an + exclusive lock. */ +#define SWITCH_FLOCK_EXCLUSIVE 2 /**< Exclusive lock. Only one process + may hold an exclusive lock at any + given time. This is analogous to + a "write lock". */ + +#define SWITCH_FLOCK_TYPEMASK 0x000F /**< mask to extract lock type */ +#define SWITCH_FLOCK_NONBLOCK 0x0010 /**< do not block while acquiring the + file lock */ + + /** @} */ + /** * @defgroup switch_file_open_flags File Open Flags/Routines * @ingroup switch_file_io @@ -711,6 +734,8 @@ SWITCH_DECLARE(switch_status_t) switch_file_seek(switch_file_t * thefile, switch */ SWITCH_DECLARE(switch_status_t) switch_file_close(switch_file_t * thefile); +SWITCH_DECLARE(switch_status_t) switch_file_lock(switch_file_t * thefile, int type); + /** * Delete the specified file. * @param path The full path to the file (using / on all systems) diff --git a/src/switch.c b/src/switch.c index 9028749c2e..10068a1bb1 100644 --- a/src/switch.c +++ b/src/switch.c @@ -38,6 +38,7 @@ #endif #include +#include "private/switch_core_pvt.h" /* pid filename: Stores the process id of the freeswitch process */ #define PIDFILE "freeswitch.pid" @@ -198,6 +199,8 @@ void WINAPI service_main(DWORD numArgs, char **args) int main(int argc, char *argv[]) { char pid_path[256] = ""; /* full path to the pid file */ + char pid_buffer[32] = ""; /* pid string */ + switch_size_t pid_len; const char *err = NULL; /* error value for return from freeswitch initialization */ #ifndef WIN32 int nf = 0; /* TRUE if we are running in nofork mode */ @@ -205,7 +208,6 @@ int main(int argc, char *argv[]) char *runas_group = NULL; #endif int nc = 0; /* TRUE if we are running in noconsole mode */ - FILE *f; /* file handle to the pid file */ pid_t pid = 0; int x; int die = 0; @@ -215,6 +217,9 @@ int main(int argc, char *argv[]) int high_prio = 0; switch_core_flag_t flags = SCF_USE_SQL; int status; + switch_file_t *fd; + switch_memory_pool_t *pool = NULL; + #ifdef WIN32 SERVICE_TABLE_ENTRY dispatchTable[] = { @@ -417,25 +422,46 @@ int main(int argc, char *argv[]) } #endif + if (apr_initialize() != SWITCH_STATUS_SUCCESS) { + fprintf(stderr, "FATAL ERROR! Could not initilize APR\n"); + return 255; + } + + switch_core_set_globals(); + + pid = getpid(); + + snprintf(pid_path, sizeof(pid_path), "%s%s%s", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR, pfile); + snprintf(pid_buffer, sizeof(pid_buffer), "%d", pid); + pid_len = strlen(pid_buffer); + + apr_pool_create(&pool, NULL); + if (switch_file_open(&fd, + pid_path, + SWITCH_FOPEN_WRITE | SWITCH_FOPEN_CREATE, + SWITCH_FPROT_UREAD | SWITCH_FPROT_UWRITE, + pool) != SWITCH_STATUS_SUCCESS) { + fprintf(stderr, "Cannot open pid file %s.\n", pid_path); + return 255; + } + + if (switch_file_lock(fd, SWITCH_FLOCK_EXCLUSIVE | SWITCH_FLOCK_NONBLOCK) != SWITCH_STATUS_SUCCESS) { + fprintf(stderr, "Cannot lock pid file %s.\n", pid_path); + return 255; + } + + switch_file_write(fd, pid_buffer, &pid_len); + if (switch_core_init_and_modload(flags, nc ? SWITCH_FALSE : SWITCH_TRUE, &err) != SWITCH_STATUS_SUCCESS) { fprintf(stderr, "Cannot Initilize [%s]\n", err); return 255; } - snprintf(pid_path, sizeof(pid_path), "%s%s%s", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR, pfile); - if ((f = fopen(pid_path, "w")) == 0) { - fprintf(stderr, "Cannot open pid file %s.\n", pid_path); - return 255; - } - - fprintf(f, "%d", pid = getpid()); - fflush(f); - switch_core_runtime_loop(nc); status = switch_core_destroy(); - fclose(f); + switch_file_close(fd); unlink(pid_path); return status; diff --git a/src/switch_apr.c b/src/switch_apr.c index e5beea84dd..33003f5e13 100644 --- a/src/switch_apr.c +++ b/src/switch_apr.c @@ -328,6 +328,11 @@ SWITCH_DECLARE(switch_status_t) switch_file_close(switch_file_t * thefile) return apr_file_close(thefile); } +SWITCH_DECLARE(switch_status_t) switch_file_lock(switch_file_t * thefile, int type) +{ + return apr_file_lock(thefile, type); +} + SWITCH_DECLARE(switch_status_t) switch_file_rename(const char *from_path, const char *to_path, switch_memory_pool_t *pool) { return apr_file_rename(from_path, to_path, pool);