Navigation


Changeset 1111:84162710428e in freeDiameter


Ignore:
Timestamp:
May 13, 2013, 12:37:12 PM (11 years ago)
Author:
Sebastien Decugis <sdecugis@freediameter.net>
Branch:
default
Children:
1112:d87cee14b051, 1114:b6885b0d8b10
Phase:
public
Message:

Cleanup to avoid sending several terminate event

File:
1 edited

Legend:

Unmodified
Added
Removed
  • libfdcore/core.c

    r1107 r1111  
    4949#endif /* GNUTLS_VERSION_210 */
    5050
    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 
    6651/* Thread that process incoming events on the main queue -- and terminates the framework when requested */
    6752static pthread_t core_runner = (pthread_t)NULL;
    6853
    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()) */
     55static 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;
     63static pthread_mutex_t core_mtx = PTHREAD_MUTEX_INITIALIZER;
     64static pthread_cond_t  core_cnd = PTHREAD_COND_INITIALIZER;
     65
     66static 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
     75static 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
     84static 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
     97static 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
    74123
    75124static void * core_runner_thread(void * arg)
    76125{
    77         if (arg && (*(int *)arg == CORE_MODE_IMMEDIATE))
    78                 goto end;
    79        
    80126        fd_log_threadname("fD Core Runner");
     127       
     128        core_state_wait(CORE_RUNNING);
    81129       
    82130        /* Handle events incoming on the main event queue */
     
    110158       
    111159end:
    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();
    133161       
    134162        return NULL;
     
    148176{
    149177        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        }
    150183       
    151184        /* Initialize the library -- must come first since it initializes the debug facility */
     
    193226        CHECK_FCT( fd_p_expi_init() );
    194227       
     228        core_state_set(CORE_LIBS_INIT);
     229       
    195230        /* Next thing is to parse the config, leave this for a different function */
    196231        return 0;
     
    230265        free(buf);     
    231266               
     267        core_state_set(CORE_CONF_READY);
     268       
    232269        return 0;
    233270}
     
    236273int fd_core_waitstartcomplete(void)
    237274{
    238         int ret = 0;
    239        
    240275        TRACE_ENTRY("");
    241276       
    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);
    253278}
    254279
     
    264289        /* Start the core runner thread that handles main events (until shutdown) */
    265290        CHECK_POSIX( pthread_create(&core_runner, NULL, core_runner_thread, NULL) );
    266 
     291       
    267292        /* Unlock threads waiting into fd_core_waitstartcomplete */
    268         CHECK_FCT( signal_framework_ready() );
     293        core_state_set(CORE_RUNNING);
    269294       
    270295        /* Ok, everything is running now... */
     
    276301int fd_core_shutdown(void)
    277302{
    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);
    280309                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. */
    292319int fd_core_wait_shutdown_complete(void)
    293320{
    294321        int ret;
     322        enum core_state cur_state = core_state_get();
    295323        void * th_ret = NULL;
    296324       
    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.