diff --git a/common/os_calls.c b/common/os_calls.c index 2b4e0e9b..c701bd22 100644 --- a/common/os_calls.c +++ b/common/os_calls.c @@ -60,6 +60,7 @@ #include #include #include +#include #endif #include @@ -1474,6 +1475,17 @@ g_sleep(int msecs) #endif } +/*****************************************************************************/ +void +g_sleep_secs(int secs) +{ +#if defined(_WIN32) + Sleep(secs * 1000); +#else + sleep(secs); +#endif +} + /*****************************************************************************/ int g_sck_last_error_would_block(int sck) @@ -2105,6 +2117,17 @@ g_memcmp(const void *s1, const void *s2, int len) return memcmp(s1, s2, len); } +/*****************************************************************************/ +int +g_ftruncate(int fd, int length) +{ +#if defined(_WIN32) + return -1; +#else + return ftruncate(fd, length); +#endif +} + /*****************************************************************************/ /* returns -1 on error, else return handle or file descriptor */ int @@ -2246,6 +2269,31 @@ g_file_seek(int fd, int offset) #endif } +/*****************************************************************************/ +/* move file pointer relative to end of file, + * returns offset on success, -1 on failure */ +int +g_file_seek_rel_end(int fd, int offset) +{ +#if defined(_WIN32) + int rv; + + rv = (int)SetFilePointer((HANDLE)fd, offset, 0, FILE_END); + + if (rv == (int)INVALID_SET_FILE_POINTER) + { + return -1; + } + else + { + return rv; + } + +#else + return (int)lseek(fd, offset, SEEK_END); +#endif +} + /*****************************************************************************/ /* do a write lock on a file */ /* return boolean */ @@ -3044,6 +3092,35 @@ g_get_proc_address(long lib, const char *name) #endif } +/*****************************************************************************/ +/* does not work in win32 */ +void * +g_map_file_shared(int fd, int length) +{ + void *mapped; + + mapped = mmap(NULL, + length, + PROT_READ|PROT_WRITE, + MAP_SHARED, + fd, + 0); + + /* MAP_FAILED != NULL but mmap() will not return 0 unless MAP_FIXED is + * specified. */ + if (mapped == MAP_FAILED) + mapped = NULL; + return mapped; +} + +/*****************************************************************************/ +/* does not work in win32 */ +int +g_unmap_file_shared(void *mapped, int length) +{ + return munmap(mapped, length); +} + /*****************************************************************************/ /* does not work in win32 */ int diff --git a/common/os_calls.h b/common/os_calls.h index b52a84df..40701e2d 100644 --- a/common/os_calls.h +++ b/common/os_calls.h @@ -86,6 +86,7 @@ int g_sck_can_recv(int sck, int millis); int g_sck_select(int sck1, int sck2); void g_write_ip_address(int rcv_sck, char* ip_address, int bytes); void g_sleep(int msecs); +void g_sleep_secs(int secs); tintptr g_create_wait_obj(const char *name); tintptr g_create_wait_obj_from_socket(tintptr socket, int write); void g_delete_wait_obj_from_socket(tintptr wait_obj); @@ -98,6 +99,7 @@ int g_obj_wait(tintptr* read_objs, int rcount, tintptr* write_objs, void g_random(char* data, int len); int g_abs(int i); int g_memcmp(const void* s1, const void* s2, int len); +int g_ftruncate(int fd, int length); int g_file_open(const char* file_name); int g_file_open_ex(const char *file_name, int aread, int awrite, int acreate, int atrunc); @@ -105,6 +107,7 @@ int g_file_close(int fd); int g_file_read(int fd, char* ptr, int len); int g_file_write(int fd, const char *ptr, int len); int g_file_seek(int fd, int offset); +int g_file_seek_rel_end(int fd, int offset); int g_file_lock(int fd, int start, int len); int g_chmod_hex(const char* filename, int flags); int g_chown(const char* name, int uid, int gid); @@ -142,6 +145,8 @@ int g_strtrim(char* str, int trim_flags); long g_load_library(char* in); int g_free_library(long lib); void* g_get_proc_address(long lib, const char* name); +void* g_map_file_shared(int fd, int length); +int g_unmap_file_shared(void *mapped, int length); int g_system(char* aexec); char* g_get_strerror(void); int g_get_errno(void); diff --git a/common/thread_calls.c b/common/thread_calls.c index 4ce25897..b55b694f 100644 --- a/common/thread_calls.c +++ b/common/thread_calls.c @@ -112,6 +112,34 @@ tc_mutex_create(void) #endif } +/*****************************************************************************/ +int +tc_shared_mutex_create(tbus mutex) +{ +#if defined(_WIN32) + /* Not implemented yet */ + return 1; +#else + pthread_mutexattr_t mutexattr; + int rc; + + rc = pthread_mutexattr_init(&mutexattr); + if (rc != 0) + { + return 1; + } + + rc = pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED); + if (rc != 0) + { + return 1; + } + + rc = pthread_mutex_init((pthread_mutex_t *)mutex, &mutexattr); + return rc; +#endif +} + /*****************************************************************************/ void tc_mutex_delete(tbus mutex) @@ -140,6 +168,22 @@ tc_mutex_lock(tbus mutex) #endif } +/*****************************************************************************/ +int +tc_mutex_timed_lock(tbus mutex, int timeout_ms) +{ +#if defined(_WIN32) + WaitForSingleObject((HANDLE)mutex, timeout_ms); + return 0; +#else + struct timespec timeout; + timeout.tv_sec = timeout_ms / 1000; + timeout.tv_nsec = ((long)timeout_ms % 1000) * 1000; + + return pthread_mutex_timedlock((pthread_mutex_t *)mutex, &timeout); +#endif +} + /*****************************************************************************/ int tc_mutex_unlock(tbus mutex) diff --git a/common/thread_calls.h b/common/thread_calls.h index c8b6640a..6f4921ae 100644 --- a/common/thread_calls.h +++ b/common/thread_calls.h @@ -31,11 +31,15 @@ int tc_threadid_equal(tbus tid1, tbus tid2); tbus tc_mutex_create(void); +int +tc_shared_mutex_create(tbus mutex); void tc_mutex_delete(tbus mutex); int tc_mutex_lock(tbus mutex); int +tc_mutex_timed_lock(tbus mutex, int timeout_ms); +int tc_mutex_unlock(tbus mutex); tbus tc_sem_create(int init_count); diff --git a/sesman/session.c b/sesman/session.c index d5e9a2b5..1534d467 100644 --- a/sesman/session.c +++ b/sesman/session.c @@ -40,17 +40,6 @@ #include #endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - #include "sesman.h" #include "libscp_types.h" #include "xauth.h" @@ -121,16 +110,29 @@ dumpItemsToString(struct list *self, char *outstr, int len) * */ static int +#ifdef DEBUG_SESSION_LOCK +sesshm_lock(const char *caller_func, int caller_line) +#else sesshm_lock() +#endif { #ifdef DONT_USE_SHM return 0; #else - int rc = pthread_mutex_lock(&g_shm_mapping->mutex); + int rc; + +#ifdef DEBUG_SESSION_LOCK + log_message(LOG_LEVEL_DEBUG, + "pid %d tid %d: %s() called from %s at line %d", + g_getpid(), (int)tc_get_threadid(), __func__, + caller_func, caller_line); +#endif + + rc = tc_mutex_lock((tbus)&g_shm_mapping->mutex); if (rc != 0) { log_message(LOG_LEVEL_ERROR, - "pthread_mutex_lock() failed (%d)", errno); + "tc_mutex_lock() failed (%d)", g_get_errno()); } return rc; #endif @@ -146,18 +148,26 @@ sesshm_lock() */ #ifndef DONT_USE_SHM static int +#ifdef DEBUG_SESSION_LOCK +sesshm_try_lock(const char *caller_func, int caller_line) +#else sesshm_try_lock() +#endif { - return 0; - struct timespec timeout; - timeout.tv_sec = 1; - timeout.tv_nsec = 0; + int rc; - int rc = pthread_mutex_timedlock(&g_shm_mapping->mutex, &timeout); +#ifdef DEBUG_SESSION_LOCK + log_message(LOG_LEVEL_DEBUG, + "pid %d tid %d: %s() called from %s at line %d", + g_getpid(), (int)tc_get_threadid(), __func__, + caller_func, caller_line); +#endif + + rc = tc_mutex_timed_lock((tbus)&g_shm_mapping->mutex, 1 * 1000); if (rc != 0) { log_message(LOG_LEVEL_ERROR, - "pthread_mutex_timedlock() failed (%d)", errno); + "tc_mutex_timed_lock() failed (%d)", g_get_errno()); } return rc; } @@ -172,16 +182,29 @@ sesshm_try_lock() * */ static int +#ifdef DEBUG_SESSION_LOCK +sesshm_unlock(const char *caller_func, int caller_line) +#else sesshm_unlock() +#endif { #ifdef DONT_USE_SHM return 0; #else - int rc = pthread_mutex_unlock(&g_shm_mapping->mutex); + int rc; + +#ifdef DEBUG_SESSION_LOCK + log_message(LOG_LEVEL_DEBUG, + "pid %d tid %d: %s() called from %s at line %d", + g_getpid(), (int)tc_get_threadid(), __func__, + caller_func, caller_line); +#endif + + rc = tc_mutex_unlock((tbus) &g_shm_mapping->mutex); if (rc != 0) { log_message(LOG_LEVEL_ERROR, - "pthread_mutex_unlock() failed (%d)", errno); + "tc_mutex_unlock() failed (%d)", g_get_errno()); } return rc; #endif @@ -189,50 +212,9 @@ sesshm_unlock() #ifdef DEBUG_SESSION_LOCK -#define sesshm_try_lock() \ - ({ \ - log_message(LOG_LEVEL_DEBUG, \ - "pid %d tid %d: sesshm_try_lock() called from %s at line %d", \ - getpid(), (int)tc_get_threadid(), __func__, __LINE__); \ - sesshm_try_lock(); \ - }) -#define sesshm_lock() \ - { \ - log_message(LOG_LEVEL_DEBUG, \ - "pid %d tid %d: sesshm_lock() called from %s at line %d", \ - getpid(), (int)tc_get_threadid(), __func__, __LINE__); \ - sesshm_lock(); \ - } -#define sesshm_unlock() \ - { \ - log_message(LOG_LEVEL_DEBUG, \ - "pid %d tid %d: sesshm_unlock() called from %s at line %d", \ - getpid(), (int)tc_get_threadid(), __func__, __LINE__); \ - sesshm_unlock(); \ - } -#endif - - -/******************************************************************************/ -/** - * - * @brief map the file fd into memory using mmap - * @return pointer to the mapping - * - */ -#ifndef DONT_USE_SHM -static struct session_shared_data * -sesshm_map(int fd) -{ - g_shm_mapping = (struct session_shared_data *) mmap(NULL, - SESMAN_SHAREDMEM_LENGTH, - PROT_READ|PROT_WRITE, - MAP_SHARED, - fd, - 0); - close(fd); - return g_shm_mapping; -} +#define sesshm_try_lock() sesshm_try_lock(__func__, __LINE__) +#define sesshm_lock() sesshm_lock(__func__, __LINE__) +#define sesshm_unlock() sesshm_unlock(__func__, __LINE__) #endif @@ -247,13 +229,19 @@ sesshm_map(int fd) static void * sesshm_thread(void *arg) { - int pid = g_getpid(); + int pid; + + pid = g_getpid(); while (g_sesshm_thread_going) { - sleep(SESMAN_SHAREDMEM_HEARTBEAT_INTERVAL); + g_sleep_secs(SESMAN_SHAREDMEM_HEARTBEAT_INTERVAL); if (g_pid == pid) { + int current_time; + struct session_chain *tmp; + struct session_chain *prev; + /* Daemon process * Check that the file hasn't been hijacked by a new daemon * process and that the heartbeat hasn't timed out for the @@ -267,9 +255,9 @@ sesshm_thread(void *arg) exit(1); } - int current_time = g_time1(); - struct session_chain *tmp = g_sessions; - struct session_chain *prev = 0; + current_time = g_time1(); + tmp = g_sessions; + prev = 0; while (tmp != 0) { if (tmp->item == 0) @@ -364,55 +352,43 @@ sesshm_create_new_shm() log_message(LOG_LEVEL_INFO, "Creating shm file %s", SESMAN_SHAREDMEM_FILENAME); - unlink(SESMAN_SHAREDMEM_FILENAME); - fd = open(SESMAN_SHAREDMEM_FILENAME, O_CREAT|O_RDWR, 00600); + g_file_delete(SESMAN_SHAREDMEM_FILENAME); + fd = g_file_open_ex(SESMAN_SHAREDMEM_FILENAME, 1, 1, 1, 0); if (fd == -1) { - log_message(LOG_LEVEL_ERROR, "open() failed (%d)", errno); + log_message(LOG_LEVEL_ERROR, "open() failed (%d)", g_get_errno()); return 1; } - rc = ftruncate(fd, SESMAN_SHAREDMEM_LENGTH); + rc = g_ftruncate(fd, SESMAN_SHAREDMEM_LENGTH); if (rc != 0) { - log_message(LOG_LEVEL_ERROR, "truncate() failed (%d)", errno); + log_message(LOG_LEVEL_ERROR, "truncate() failed (%d)", g_get_errno()); return 2; } /* Map it into memory */ - g_shm_mapping = sesshm_map(fd); - if (g_shm_mapping == MAP_FAILED) + g_shm_mapping = ((struct session_shared_data *) + g_map_file_shared(fd, SESMAN_SHAREDMEM_LENGTH)); + g_file_close(fd); + if (g_shm_mapping == NULL) { - log_message(LOG_LEVEL_ERROR, "mmap() failed (%d)", errno); + log_message(LOG_LEVEL_ERROR, "mmap() failed (%d)", g_get_errno()); return 3; } /* Initalise mutex */ - pthread_mutexattr_t mutexattr; - rc = pthread_mutexattr_init(&mutexattr); + rc = tc_shared_mutex_create((tbus) &g_shm_mapping->mutex); if (rc != 0) { - log_message(LOG_LEVEL_ERROR, "pthread_mutexattr_init() failed (%d)", - errno); - return 4; - } - rc = pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED); - if (rc != 0) - { - log_message(LOG_LEVEL_ERROR, - "pthread_mutexattr_setpshared() failed (%d)", errno); - return 5; - } - pthread_mutex_init(&g_shm_mapping->mutex, &mutexattr); - if (rc != 0) - { - log_message(LOG_LEVEL_ERROR, "pthread_mutex_init() failed (%d)", errno); + log_message(LOG_LEVEL_ERROR, "tc_shared_mutex_create() failed (%d)", + g_get_errno()); return 6; } /* Initialise data */ sesshm_lock(); - strncpy(g_shm_mapping->tag, SESMAN_SHAREDMEM_TAG, - sizeof(g_shm_mapping->tag)); + g_strncpy(g_shm_mapping->tag, SESMAN_SHAREDMEM_TAG, + sizeof(g_shm_mapping->tag)); g_shm_mapping->data_format_version = SESMAN_SHAREDMEM_FORMAT_VERSION; g_shm_mapping->max_sessions = SESMAN_SHAREDMEM_MAX_SESSIONS; g_shm_mapping->daemon_pid = g_pid; @@ -441,26 +417,27 @@ sesshm_try_open_existing_shm() int rc; int fd; int i; + off_t end; + char tag[SESMAN_SHAREDMEM_TAG_LENGTH]; log_message(LOG_LEVEL_INFO, "Looking for existing shm file %s", SESMAN_SHAREDMEM_FILENAME); /* Does the shared file already exist? */ - fd = open(SESMAN_SHAREDMEM_FILENAME, O_RDWR); + fd = g_file_open_ex(SESMAN_SHAREDMEM_FILENAME, 1, 1, 0, 0); if (fd == -1) { - log_message(LOG_LEVEL_ERROR, "open() failed (%d)", errno); + log_message(LOG_LEVEL_ERROR, "open() failed (%d)", g_get_errno()); return 1; } - char tag[SESMAN_SHAREDMEM_TAG_LENGTH]; - rc = read(fd, tag, SESMAN_SHAREDMEM_TAG_LENGTH); + rc = g_file_read(fd, tag, SESMAN_SHAREDMEM_TAG_LENGTH); if (rc != SESMAN_SHAREDMEM_TAG_LENGTH) { - log_message(LOG_LEVEL_ERROR, "read() failed (%d)", errno); + log_message(LOG_LEVEL_ERROR, "read() failed (%d)", g_get_errno()); return 2; } - if (strncmp(tag, SESMAN_SHAREDMEM_TAG, SESMAN_SHAREDMEM_TAG_LENGTH)) + if (g_strncmp(tag, SESMAN_SHAREDMEM_TAG, SESMAN_SHAREDMEM_TAG_LENGTH)) { log_message(LOG_LEVEL_ERROR, "tag is wrong file shm file %s", SESMAN_SHAREDMEM_FILENAME); @@ -469,25 +446,27 @@ sesshm_try_open_existing_shm() } /* Is it the right size? */ - off_t end = lseek(fd, 0, SEEK_END); + end = g_file_seek_rel_end(fd, 0); if (end != SESMAN_SHAREDMEM_LENGTH) { log_message(LOG_LEVEL_ERROR, "shm file %s has wrong length", SESMAN_SHAREDMEM_FILENAME); return 4; } - rc = lseek(fd, 0, SEEK_SET); + rc = g_file_seek(fd, 0); if (rc != 0) { - log_message(LOG_LEVEL_ERROR, "seek() failed (%d)", errno); + log_message(LOG_LEVEL_ERROR, "seek() failed (%d)", g_get_errno()); return 5; } /* Map it into memory */ - g_shm_mapping = sesshm_map(fd); - if (g_shm_mapping == MAP_FAILED) + g_shm_mapping = ((struct session_shared_data *) + g_map_file_shared(fd, SESMAN_SHAREDMEM_LENGTH)); + g_file_close(fd); + if (g_shm_mapping == NULL) { - log_message(LOG_LEVEL_ERROR, "mmap() failed (%d)", errno); + log_message(LOG_LEVEL_ERROR, "mmap() failed (%d)", g_get_errno()); return 6; } @@ -496,7 +475,8 @@ sesshm_try_open_existing_shm() rc = sesshm_try_lock(); if (rc) { - log_message(LOG_LEVEL_ERROR, "sesshm_try_lock() failed (%d)", errno); + log_message(LOG_LEVEL_ERROR, "sesshm_try_lock() failed (%d)", + g_get_errno()); // XXX Should we exit(1) here instead? return 7; } @@ -504,7 +484,7 @@ sesshm_try_open_existing_shm() if (g_shm_mapping->data_format_version != SESMAN_SHAREDMEM_FORMAT_VERSION) { sesshm_unlock(); - log_message(LOG_LEVEL_ERROR, "wrong data version (%d)", errno); + log_message(LOG_LEVEL_ERROR, "wrong data version (%d)", g_get_errno()); // XXX Should we exit(1) here instead? return 8; } @@ -514,8 +494,11 @@ sesshm_try_open_existing_shm() { if (g_shm_mapping->sessions[i].shm_is_allocated) { - struct session_chain *temp = - (struct session_chain *)g_malloc(sizeof(struct session_chain), 0); + struct session_chain *temp; + + temp = + (struct session_chain *)g_malloc(sizeof(struct session_chain), + 0); temp->item = &g_shm_mapping->sessions[i]; temp->next = g_sessions; g_sessions = temp; @@ -551,11 +534,15 @@ session_init_shared() /* If it's not okay then create it */ if (rc != 0) + { rc = sesshm_create_new_shm(); + } /* Start polling thread */ if (rc == 0) + { tc_thread_create(sesshm_thread, 0); + } return rc; #endif @@ -575,16 +562,22 @@ session_close_shared() #ifdef DONT_USE_SHM return 0; #else + int rc; + g_sesshm_thread_going = 0; sesshm_lock(); if (g_shm_mapping->daemon_pid == g_getpid()) + { g_shm_mapping->daemon_pid = -1; + } sesshm_unlock(); - int rc = munmap(g_shm_mapping, SESMAN_SHAREDMEM_LENGTH); + rc = g_unmap_file_shared(g_shm_mapping, SESMAN_SHAREDMEM_LENGTH); if (rc != 0) + { return 1; + } return 0; #endif @@ -610,9 +603,9 @@ alloc_session_item() { if (!g_shm_mapping->sessions[i].shm_is_allocated) { - memset(&g_shm_mapping->sessions[i], - 0, - sizeof(g_shm_mapping->sessions[i])); + g_memset(&g_shm_mapping->sessions[i], + 0, + sizeof(g_shm_mapping->sessions[i])); g_shm_mapping->sessions[i].shm_is_allocated = 1; sesshm_unlock(); return &g_shm_mapping->sessions[i]; @@ -636,17 +629,24 @@ alloc_session_item() static int validate_session_item_ptr(struct session_item *item) { - char *start = (char *) &g_shm_mapping->sessions[0]; - int diff = (char *) item - start; - int size = sizeof(g_shm_mapping->sessions[0]); - int valid = (diff % size == 0 - && diff >= 0 - && (diff / size < g_shm_mapping->max_sessions)); + char *start; + int diff; + int size; + int valid; + + start = (char *) &g_shm_mapping->sessions[0]; + diff = (char *) item - start; + size = sizeof(g_shm_mapping->sessions[0]); + valid = (diff % size == 0 + && diff >= 0 + && (diff / size < g_shm_mapping->max_sessions)); if (!valid) + { log_message(LOG_LEVEL_ALWAYS, "validate_session_item_ptr: bad pointer %p", item); + } return valid; }