changeset 686:f83d9878bf66

Fixed in case of termination of several modules (before initialization completed)
author Sebastien Decugis <sdecugis@nict.go.jp>
date Wed, 19 Jan 2011 14:35:14 +0900
parents a0209539c044
children 026802543f57
files libfdcore/config.c libfdcore/core.c libfdcore/p_expiry.c libfdcore/queues.c libfdcore/routing_dispatch.c libfdcore/server.c libfdproto/messages.c libfdproto/sessions.c
diffstat 8 files changed, 62 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/libfdcore/config.c	Wed Jan 19 11:11:23 2011 +0900
+++ b/libfdcore/config.c	Wed Jan 19 14:35:14 2011 +0900
@@ -456,6 +456,9 @@
 {
 	TRACE_ENTRY();
 	
+	if (!fd_g_config)
+		return 0;
+	
 	/* Free the TLS parameters */
 	gnutls_priority_deinit(fd_g_config->cnf_sec_data.prio_cache);
 	gnutls_dh_params_deinit(fd_g_config->cnf_sec_data.dh_cache);
--- a/libfdcore/core.c	Wed Jan 19 11:11:23 2011 +0900
+++ b/libfdcore/core.c	Wed Jan 19 14:35:14 2011 +0900
@@ -38,8 +38,8 @@
 #include <gcrypt.h>
 
 /* The static configuration structure */
-static struct fd_config conf;
-struct fd_config * fd_g_config = &conf;
+static struct fd_config g_conf;
+struct fd_config * fd_g_config = NULL;
 
 /* gcrypt functions to support posix threads */
 GCRY_THREAD_OPTION_PTHREAD_IMPL;
@@ -61,11 +61,18 @@
 
 /* Thread that process incoming events on the main queue -- and terminates the framework when requested */
 static pthread_t core_runner = (pthread_t)NULL;
+enum core_mode {
+	CORE_MODE_EVENTS,
+	CORE_MODE_IMMEDIATE
+};
 
 static void * core_runner_thread(void * arg) 
 {
 	fd_log_threadname("Core Runner");
 	
+	if (arg && (*(int *)arg == CORE_MODE_IMMEDIATE))
+		goto end;
+	
 	/* Handle events incoming on the main event queue */
 	while (1) {
 		int code; size_t sz; void * data;
@@ -160,8 +167,6 @@
 {
 	int ret;
 	
-	memset(fd_g_config, 0, sizeof(struct fd_config));
-	
 	/* Initialize the library -- must come first since it initializes the debug facility */
 	ret = fd_libproto_init();
 	if (ret != 0) {
@@ -186,6 +191,8 @@
 	}
 	
 	/* Initialize the config with default values */
+	memset(&g_conf, 0, sizeof(struct fd_config));
+	fd_g_config = &g_conf;
 	CHECK_FCT( fd_conf_init() );
 
 	/* Add definitions of the base protocol */
@@ -268,8 +275,14 @@
 /* Initialize shutdown of the framework. This is not blocking. */
 int fd_core_shutdown(void)
 {
-	/* Signal the framework to terminate */
-	CHECK_FCT( fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, 0, NULL) );
+	if (core_runner != (pthread_t)NULL) {
+		/* Signal the framework to terminate */
+		CHECK_FCT( fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, 0, NULL) );
+	} else {
+		/* The framework was maybe not fully initialized (ex: tests) */
+		enum core_mode arg = CORE_MODE_IMMEDIATE;
+		(void) core_runner_thread(&arg);
+	}
 	
 	return 0;
 }
@@ -281,11 +294,13 @@
 	int ret;
 	void * th_ret = NULL;
 	
-	/* Just wait for core_runner_thread to complete and return gracefully */
-	ret = pthread_join(core_runner, &th_ret);
-	if (ret != 0) {
-		fprintf(stderr, "Unable to wait for main framework thread termination: %s\n", strerror(ret));
-		return ret;
+	if (core_runner != (pthread_t)NULL) {
+		/* Just wait for core_runner_thread to complete and return gracefully */
+		ret = pthread_join(core_runner, &th_ret);
+		if (ret != 0) {
+			fprintf(stderr, "Unable to wait for main framework thread termination: %s\n", strerror(ret));
+			return ret;
+		}
 	}
 	
 	return 0;
--- a/libfdcore/p_expiry.c	Wed Jan 19 11:11:23 2011 +0900
+++ b/libfdcore/p_expiry.c	Wed Jan 19 14:35:14 2011 +0900
@@ -38,8 +38,8 @@
 /* Delay for garbage collection of expired peers, in seconds */
 #define GC_TIME		120
 
-static pthread_t       exp_thr;
-static pthread_t       gc_thr;
+static pthread_t       exp_thr = (pthread_t)NULL;
+static pthread_t       gc_thr  = (pthread_t)NULL;
 static struct fd_list  exp_list = FD_LIST_INITIALIZER( exp_list );
 static pthread_cond_t  exp_cnd  = PTHREAD_COND_INITIALIZER;
 static pthread_mutex_t exp_mtx  = PTHREAD_MUTEX_INITIALIZER;
--- a/libfdcore/queues.c	Wed Jan 19 11:11:23 2011 +0900
+++ b/libfdcore/queues.c	Wed Jan 19 14:35:14 2011 +0900
@@ -59,6 +59,10 @@
 	TRACE_ENTRY("%p", queue);
 	
 	/* Note : the threads that post into this queue should already been stopped before this !!! */
+	
+	CHECK_PARAMS(queue);
+	if (*queue == NULL)
+		return 0; /* the queue was not already initialized */
 
 	/* Empty all contents */
 	while (1) {
--- a/libfdcore/routing_dispatch.c	Wed Jan 19 11:11:23 2011 +0900
+++ b/libfdcore/routing_dispatch.c	Wed Jan 19 14:35:14 2011 +0900
@@ -972,11 +972,11 @@
 static pthread_mutex_t order_lock = PTHREAD_MUTEX_INITIALIZER;
 
 /* Threads report their status */
-enum thread_state { INITIAL = 0, RUNNING = 1, TERMINATED = 2 };
+enum thread_state { NOTRUNNING = 0, RUNNING = 1 };
 static void cleanup_state(void * state_loc)
 {
 	if (state_loc)
-		*(enum thread_state *)state_loc = TERMINATED;
+		*(enum thread_state *)state_loc = NOTRUNNING;
 }
 
 /* This is the common thread code (same for routing and dispatching) */
@@ -1079,10 +1079,10 @@
 
 /* Later: make this more dynamic */
 static pthread_t rt_out = (pthread_t)NULL;
-static enum thread_state out_state = INITIAL;
+static enum thread_state out_state = NOTRUNNING;
 
 static pthread_t rt_in  = (pthread_t)NULL;
-static enum thread_state in_state = INITIAL;
+static enum thread_state in_state = NOTRUNNING;
 
 /* Initialize the routing and dispatch threads */
 int fd_rtdisp_init(void)
@@ -1090,8 +1090,8 @@
 	int i;
 	
 	/* Prepare the array for dispatch */
+	CHECK_MALLOC( disp_state = calloc(fd_g_config->cnf_dispthr, sizeof(enum thread_state)) );
 	CHECK_MALLOC( dispatch = calloc(fd_g_config->cnf_dispthr, sizeof(pthread_t)) );
-	CHECK_MALLOC( disp_state = calloc(fd_g_config->cnf_dispthr, sizeof(enum thread_state)) );
 	
 	/* Create the threads */
 	for (i=0; i < fd_g_config->cnf_dispthr; i++) {
@@ -1125,7 +1125,7 @@
 
 	/* Wait for a second for the thread to complete, by monitoring my_state */
 	fd_cpu_flush_cache();
-	if (*st != TERMINATED) {
+	if (*st != NOTRUNNING) {
 		TRACE_DEBUG(INFO, "Waiting for the %s thread to have a chance to terminate", th_name);
 		do {
 			struct timespec	 ts, ts_final;
@@ -1136,7 +1136,8 @@
 			ts_final.tv_nsec = ts.tv_nsec;
 			
 			while (TS_IS_INFERIOR( &ts, &ts_final )) {
-				if (*st == TERMINATED)
+				fd_cpu_flush_cache();
+				if (*st == NOTRUNNING)
 					break;
 				
 				usleep(100000);
@@ -1170,9 +1171,17 @@
 	/* Destroy the local queue */
 	CHECK_FCT_DO( fd_queues_fini(&fd_g_local), /* ignore */);
 	
-	/* Stop the Dispatch thread */
-	for (i=0; i < fd_g_config->cnf_dispthr; i++) {
-		stop_thread_delayed(&disp_state[i], &dispatch[i], "Dispatching");
+	/* Stop the Dispatch threads */
+	if (dispatch != NULL) {
+		for (i=0; i < fd_g_config->cnf_dispthr; i++) {
+			stop_thread_delayed(&disp_state[i], &dispatch[i], "Dispatching");
+		}
+		free(dispatch);
+		dispatch = NULL;
+	}
+	if (disp_state != NULL) {
+		free(disp_state);
+		disp_state = NULL;
 	}
 	
 	return 0;
--- a/libfdcore/server.c	Wed Jan 19 11:11:23 2011 +0900
+++ b/libfdcore/server.c	Wed Jan 19 14:35:14 2011 +0900
@@ -35,10 +35,10 @@
 
 #include "fdcore-internal.h"
 
-/* Server (listening) part of the daemon */
+/* Server (listening) part of the framework */
 
-struct fd_list		FD_SERVERS = FD_LIST_INITIALIZER(FD_SERVERS);	/* The list of all server objects */
-/* We don't need to protect this list, it is only accessed from the main daemon thread. */
+static struct fd_list	FD_SERVERS = FD_LIST_INITIALIZER(FD_SERVERS);	/* The list of all server objects */
+/* We don't need to protect this list, it is only accessed from the main framework thread. */
 
 /* Servers information */
 struct server {
@@ -82,7 +82,7 @@
 				((s->status == 2) ? "Thread terminated" :
 							  "Thread status unknown")));
 		/* Dump the client list of this server */
-		(void) pthread_mutex_lock(&s->clients_mtx);
+		CHECK_POSIX_DO( pthread_mutex_lock(&s->clients_mtx), );
 		for (cli = s->clients.next; cli != &s->clients; cli = cli->next) {
 			struct client * c = (struct client *)cli;
 			char bufts[128];
@@ -90,7 +90,7 @@
 					fd_cnx_getid(c->conn),
 					fd_log_time(&c->ts, bufts, sizeof(bufts)));
 		}
-		(void) pthread_mutex_unlock(&s->clients_mtx);
+		CHECK_POSIX_DO( pthread_mutex_unlock(&s->clients_mtx), );
 	}
 }
 
--- a/libfdproto/messages.c	Wed Jan 19 11:11:23 2011 +0900
+++ b/libfdproto/messages.c	Wed Jan 19 14:35:14 2011 +0900
@@ -1108,8 +1108,8 @@
 
 
 /******************* End-to-end counter *********************/
-uint32_t fd_eteid;
-pthread_mutex_t fd_eteid_lck = PTHREAD_MUTEX_INITIALIZER;
+static uint32_t fd_eteid;
+static pthread_mutex_t fd_eteid_lck = PTHREAD_MUTEX_INITIALIZER;
 
 void fd_msg_eteid_init(void)
 {
--- a/libfdproto/sessions.c	Wed Jan 19 11:11:23 2011 +0900
+++ b/libfdproto/sessions.c	Wed Jan 19 14:35:14 2011 +0900
@@ -121,7 +121,7 @@
 static struct fd_list	exp_sentinel = FD_LIST_INITIALIZER(exp_sentinel);	/* list of sessions ordered by their timeout date */
 static pthread_mutex_t	exp_lock = PTHREAD_MUTEX_INITIALIZER;	/* lock protecting the list. */
 static pthread_cond_t	exp_cond = PTHREAD_COND_INITIALIZER;	/* condvar used by the expiry mecahinsm. */
-static pthread_t	exp_thr; 	/* The expiry thread that handles cleanup of expired sessions */
+static pthread_t	exp_thr = (pthread_t)NULL; 	/* The expiry thread that handles cleanup of expired sessions */
 
 /* Hierarchy of the locks, to avoid deadlocks:
  *  hash lock > state lock > expiry lock
"Welcome to our mercurial repository"