Changeset 1111:84162710428e in freeDiameter for libfdcore/core.c
- Timestamp:
- May 13, 2013, 12:37:12 PM (11 years ago)
- Branch:
- default
- Children:
- 1112:d87cee14b051, 1114:b6885b0d8b10
- Phase:
- public
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
libfdcore/core.c
r1107 r1111 49 49 #endif /* GNUTLS_VERSION_210 */ 50 50 51 /* Signal extensions when the framework is completely initialized (they are waiting in fd_core_waitstartcomplete()) */52 static int is_ready = 0;53 static pthread_mutex_t is_ready_mtx = PTHREAD_MUTEX_INITIALIZER;54 static pthread_cond_t is_ready_cnd = PTHREAD_COND_INITIALIZER;55 56 static int signal_framework_ready(void)57 {58 TRACE_ENTRY("");59 CHECK_POSIX( pthread_mutex_lock( &is_ready_mtx ) );60 is_ready = 1;61 CHECK_POSIX( pthread_cond_broadcast( &is_ready_cnd ) );62 CHECK_POSIX( pthread_mutex_unlock( &is_ready_mtx ) );63 return 0;64 }65 66 51 /* Thread that process incoming events on the main queue -- and terminates the framework when requested */ 67 52 static pthread_t core_runner = (pthread_t)NULL; 68 53 69 /* How the thread is terminated */ 70 enum core_mode { 71 CORE_MODE_EVENTS, 72 CORE_MODE_IMMEDIATE 73 }; 54 /* Signal extensions when the framework is completely initialized (they are waiting in fd_core_waitstartcomplete()) */ 55 static enum core_state { 56 CORE_NOT_INIT, /* initial state */ 57 CORE_LIBS_INIT, /* fd_core_initialize was called */ 58 CORE_CONF_READY,/* Configuration was parsed, extensions are loaded */ 59 CORE_RUNNING, /* Servers and clients are started, core_runner thread is running */ 60 CORE_SHUTDOWN, /* The framework is terminating all objects */ 61 CORE_TERM /* Shutdown complete. */ 62 } core_state = CORE_NOT_INIT; 63 static pthread_mutex_t core_mtx = PTHREAD_MUTEX_INITIALIZER; 64 static pthread_cond_t core_cnd = PTHREAD_COND_INITIALIZER; 65 66 static enum core_state core_state_get(void) 67 { 68 enum core_state cur_state; 69 CHECK_POSIX_DO( pthread_mutex_lock( &core_mtx ), ); 70 cur_state = core_state; 71 CHECK_POSIX_DO( pthread_mutex_unlock( &core_mtx ), ); 72 return cur_state; 73 } 74 75 static void core_state_set(enum core_state newstate) 76 { 77 CHECK_POSIX_DO( pthread_mutex_lock( &core_mtx ), ); 78 LOG_D("Core state: %d -> %d", core_state, newstate); 79 core_state = newstate; 80 CHECK_POSIX_DO( pthread_cond_broadcast( &core_cnd ), ); 81 CHECK_POSIX_DO( pthread_mutex_unlock( &core_mtx ), ); 82 } 83 84 static int core_state_wait(enum core_state waitstate) 85 { 86 int ret; 87 CHECK_POSIX( pthread_mutex_lock( &core_mtx )); 88 pthread_cleanup_push( fd_cleanup_mutex, &core_mtx ); 89 do { 90 CHECK_POSIX_DO(ret = pthread_cond_wait(&core_cnd, &core_mtx), break); 91 } while (waitstate > core_state); 92 pthread_cleanup_pop( 0 ); 93 CHECK_POSIX( pthread_mutex_unlock( &core_mtx )); 94 return ret; 95 } 96 97 static void core_shutdown(void) 98 { 99 LOG_N( FD_PROJECT_BINARY " framework is stopping..."); 100 fd_log_threadname("fD Core Shutdown"); 101 102 /* cleanups */ 103 CHECK_FCT_DO( fd_servers_stop(), /* Stop accepting new connections */ ); 104 CHECK_FCT_DO( fd_rtdisp_cleanstop(), /* Stop dispatch thread(s) after a clean loop if possible */ ); 105 CHECK_FCT_DO( fd_peer_fini(), /* Stop all connections */ ); 106 CHECK_FCT_DO( fd_rtdisp_fini(), /* Stop routing threads and destroy routing queues */ ); 107 108 CHECK_FCT_DO( fd_ext_term(), /* Cleanup all extensions */ ); 109 CHECK_FCT_DO( fd_rtdisp_cleanup(), /* destroy remaining handlers */ ); 110 111 GNUTLS_TRACE( gnutls_global_deinit() ); 112 113 CHECK_FCT_DO( fd_conf_deinit(), ); 114 115 CHECK_FCT_DO( fd_event_trig_fini(), ); 116 117 fd_log_debug(FD_PROJECT_BINARY " framework is terminated."); 118 119 fd_libproto_fini(); 120 121 } 122 74 123 75 124 static void * core_runner_thread(void * arg) 76 125 { 77 if (arg && (*(int *)arg == CORE_MODE_IMMEDIATE))78 goto end;79 80 126 fd_log_threadname("fD Core Runner"); 127 128 core_state_wait(CORE_RUNNING); 81 129 82 130 /* Handle events incoming on the main event queue */ … … 110 158 111 159 end: 112 TRACE_DEBUG(INFO, FD_PROJECT_BINARY " framework is stopping..."); 113 fd_log_threadname("fD Core Shutdown"); 114 115 /* cleanups */ 116 CHECK_FCT_DO( fd_servers_stop(), /* Stop accepting new connections */ ); 117 CHECK_FCT_DO( fd_rtdisp_cleanstop(), /* Stop dispatch thread(s) after a clean loop if possible */ ); 118 CHECK_FCT_DO( fd_peer_fini(), /* Stop all connections */ ); 119 CHECK_FCT_DO( fd_rtdisp_fini(), /* Stop routing threads and destroy routing queues */ ); 120 121 CHECK_FCT_DO( fd_ext_term(), /* Cleanup all extensions */ ); 122 CHECK_FCT_DO( fd_rtdisp_cleanup(), /* destroy remaining handlers */ ); 123 124 GNUTLS_TRACE( gnutls_global_deinit() ); 125 126 CHECK_FCT_DO( fd_conf_deinit(), ); 127 128 CHECK_FCT_DO( fd_event_trig_fini(), ); 129 130 fd_log_debug(FD_PROJECT_BINARY " framework is terminated."); 131 132 fd_libproto_fini(); 160 core_shutdown(); 133 161 134 162 return NULL; … … 148 176 { 149 177 int ret; 178 179 if (core_state_get() != CORE_NOT_INIT) { 180 fprintf(stderr, "fd_core_initialize() called more than once!\n"); 181 return EINVAL; 182 } 150 183 151 184 /* Initialize the library -- must come first since it initializes the debug facility */ … … 193 226 CHECK_FCT( fd_p_expi_init() ); 194 227 228 core_state_set(CORE_LIBS_INIT); 229 195 230 /* Next thing is to parse the config, leave this for a different function */ 196 231 return 0; … … 230 265 free(buf); 231 266 267 core_state_set(CORE_CONF_READY); 268 232 269 return 0; 233 270 } … … 236 273 int fd_core_waitstartcomplete(void) 237 274 { 238 int ret = 0;239 240 275 TRACE_ENTRY(""); 241 276 242 CHECK_POSIX( pthread_mutex_lock( &is_ready_mtx ) ); 243 pthread_cleanup_push( fd_cleanup_mutex, &is_ready_mtx ); 244 245 while (!ret && !is_ready) { 246 CHECK_POSIX_DO( ret = pthread_cond_wait( &is_ready_cnd, &is_ready_mtx ), ); 247 } 248 249 pthread_cleanup_pop( 0 ); 250 CHECK_POSIX( pthread_mutex_unlock( &is_ready_mtx ) ); 251 252 return ret; 277 return core_state_wait(CORE_RUNNING); 253 278 } 254 279 … … 264 289 /* Start the core runner thread that handles main events (until shutdown) */ 265 290 CHECK_POSIX( pthread_create(&core_runner, NULL, core_runner_thread, NULL) ); 266 291 267 292 /* Unlock threads waiting into fd_core_waitstartcomplete */ 268 CHECK_FCT( signal_framework_ready());293 core_state_set(CORE_RUNNING); 269 294 270 295 /* Ok, everything is running now... */ … … 276 301 int fd_core_shutdown(void) 277 302 { 278 if (core_runner != (pthread_t)NULL) { 279 /* Signal the framework to terminate */ 303 enum core_state cur_state = core_state_get(); 304 305 if (cur_state < CORE_RUNNING) { 306 core_shutdown(); 307 } else if (cur_state == CORE_RUNNING) { 308 core_state_set(CORE_SHUTDOWN); 280 309 CHECK_FCT( fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, 0, NULL) ); 281 } else { 282 /* The framework was maybe not fully initialized (ex: tests) */ 283 enum core_mode arg = CORE_MODE_IMMEDIATE; 284 (void) core_runner_thread(&arg); 285 } 286 287 return 0; 288 } 289 290 291 /* Wait for the shutdown to be complete -- this must always be called after fd_core_shutdown to reclaim some resources. */ 310 } 311 312 /* Other case, the framework is already shutting down */ 313 314 return 0; 315 } 316 317 318 /* Wait for the shutdown to be complete -- this must be called after fd_core_shutdown to reclaim some resources. */ 292 319 int fd_core_wait_shutdown_complete(void) 293 320 { 294 321 int ret; 322 enum core_state cur_state = core_state_get(); 295 323 void * th_ret = NULL; 296 324 297 if (core_runner != (pthread_t)NULL) { 298 /* Just wait for core_runner_thread to complete and return gracefully */ 299 ret = pthread_join(core_runner, &th_ret); 300 if (ret != 0) { 301 TRACE_ERROR( "Unable to wait for main framework thread termination: %s", strerror(ret)); 302 return ret; 303 } 304 } 305 306 return 0; 307 } 308 309 310 311 325 if (cur_state == CORE_TERM) 326 return 0; 327 328 CHECK_FCT(core_state_wait(CORE_SHUTDOWN)); 329 330 /* Just wait for core_runner_thread to complete and return gracefully */ 331 CHECK_POSIX(pthread_join(core_runner, &th_ret)); 332 333 core_state_set(CORE_TERM); 334 335 return 0; 336 } 337 338 339 340
Note: See TracChangeset
for help on using the changeset viewer.