/* * Check that the counts of running and retry servers stored in struct service * are accurate */ static unsigned service_count_check( struct service *sp, unsigned running_servers, unsigned retry_servers ) { char *sid = SVC_ID( sp ) ; int error_count = 0 ; const char *func = "service_count_check" ; if ( SVC_RUNNING_SERVERS( sp ) != running_servers ) { msg( LOG_ERR, func, "service %s: actual running servers = %d, known running servers = %d", sid, running_servers, SVC_RUNNING_SERVERS( sp ) ) ; error_count++ ; } if ( SVC_RETRIES( sp ) != retry_servers ) { msg( LOG_ERR, func, "service %s: actual retry servers = %d, known retry servers = %d", sid, retry_servers, SVC_RETRIES( sp ) ) ; error_count++ ; } if ( error_count && debug.on ) msg( LOG_DEBUG, func, "%s: %d errors detected", sid, error_count ) ; return( error_count ) ; }
void svc_dump( const struct service *sp, int fd ) { tabprint( fd, 0, "Service = %s\n", SC_NAME( SVC_CONF( sp ) ) ) ; tabprint( fd, 1, "State = %s\n", nv_get_name( service_states, (int) SVC_STATE(sp) ) ) ; sc_dump( SVC_CONF( sp ), fd, 1, FALSE ) ; if ( SVC_IS_ACTIVE(sp) ) { tabprint( fd, 1, "running servers = %d\n", SVC_RUNNING_SERVERS(sp) ) ; tabprint( fd, 1, "retry servers = %d\n", SVC_RETRIES(sp) ) ; tabprint( fd, 1, "attempts = %d\n", SVC_ATTEMPTS(sp) ) ; tabprint( fd, 1, "service fd = %d\n", SVC_FD(sp) ) ; } Sputchar( fd, '\n' ) ; }
static void consistency_check( enum check_type type ) { int fd ; fd_set socket_mask_copy ; unsigned u ; int errors ; unsigned total_running_servers = 0 ; unsigned total_retry_servers = 0 ; unsigned error_count = 0 ; bool_int service_count_check_failed = FALSE ; const char *func = "consistency_check" ; socket_mask_copy = ps.rws.socket_mask ; for ( u = 0 ; u < pset_count( SERVICES( ps ) ) ; u++ ) { register struct service *sp = SP( pset_pointer( SERVICES( ps ), u ) ) ; char *sid = SVC_ID( sp ) ; unsigned running_servers ; unsigned retry_servers ; error_count += refcount_check( sp, &running_servers, &retry_servers ) ; if ( SVC_IS_AVAILABLE( sp ) || SVC_IS_DISABLED ( sp ) ) { /* * In this case, there may be some servers running */ if ( FD_ISSET( SVC_FD( sp ), &socket_mask_copy ) ) { if ( SVC_IS_DISABLED( sp ) ) { msg( LOG_ERR, func, "fd of disabled service %s still in socket mask", sid ) ; error_count++ ; } FD_CLR( SVC_FD( sp ), &socket_mask_copy ) ; } error_count += thread_check( sp, running_servers, retry_servers ) ; errors = service_count_check( sp, running_servers, retry_servers ) ; if ( ! errors && ! service_count_check_failed ) { total_retry_servers += retry_servers ; total_running_servers += running_servers ; } if ( errors ) { service_count_check_failed = TRUE ; error_count += errors ; } if ( SVC_IS_DISABLED( sp ) && SVC_RUNNING_SERVERS( sp ) == 0 ) { msg( LOG_ERR, func, "disabled service %s has 0 running servers\n", sid ) ; error_count++ ; continue ; } } else { msg( LOG_ERR, func, "service %s not started", SVC_ID( sp ) ) ; error_count++ ; } } if ( ! service_count_check_failed ) { if ( total_running_servers != pset_count( SERVERS( ps ) ) ) { msg( LOG_ERR, func, "total running servers (%d) != number of running servers (%d)", total_running_servers, pset_count( SERVERS( ps ) ) ) ; error_count++ ; } if ( total_retry_servers != pset_count( RETRIES( ps ) ) ) { msg( LOG_ERR, func, "total retry servers (%d) != number of retry servers (%d)", total_retry_servers, pset_count( RETRIES( ps ) ) ) ; error_count++ ; } } /* * Check if there are any descriptors set in socket_mask_copy */ for ( fd = 0 ; fd < ps.ros.max_descriptors ; fd++ ) if ( FD_ISSET( fd, &socket_mask_copy ) && ((fd != signals_pending[0]) && fd != signals_pending[1])) { msg( LOG_ERR, func, "descriptor %d set in socket mask but there is no service for it", fd ) ; error_count++ ; } if ( error_count != 0 ) msg( LOG_WARNING, func, "Consistency check detected %d errors", error_count ) ; else if ( type == USER_REQUESTED || debug.on ) msg( LOG_INFO, func, "Consistency check passed" ) ; if( type == PERIODIC ) if ( xtimer_add( periodic_check, ps.ros.cc_interval ) == -1 ) msg( LOG_ERR, func, "Failed to start consistency timer" ) ; }
/* * Activate a service. */ status_e svc_activate( struct service *sp ) { struct service_config *scp = SVC_CONF( sp ) ; status_e status ; const char *func = "svc_activate" ; /* No activation for MUXCLIENTS. */ if (SC_IS_MUXCLIENT( scp )) { return( OK ); } if( SC_IPV4( scp ) ) { SVC_FD(sp) = socket( AF_INET, SC_SOCKET_TYPE( scp ), SC_PROTOVAL( scp ) ) ; } else if( SC_IPV6( scp ) ) { SVC_FD(sp) = socket( AF_INET6, SC_SOCKET_TYPE( scp ), SC_PROTOVAL( scp ) ) ; } if ( SVC_FD(sp) == -1 ) { msg( LOG_ERR, func, "socket creation failed (%m). service = %s", SC_ID( scp ) ) ; return( FAILED ) ; } if ( set_fd_modes( sp ) == FAILED ) { (void) Sclose( SVC_FD(sp) ) ; return( FAILED ) ; } #ifndef NO_RPC if ( SC_IS_RPC( scp ) ) status = activate_rpc( sp ) ; else #endif /* ! NO_RPC */ status = activate_normal( sp ) ; if ( status == FAILED ) { (void) Sclose( SVC_FD(sp) ) ; return( FAILED ) ; } #ifdef HAVE_MDNS xinetd_mdns_register(scp); #endif if ( log_start( sp, &SVC_LOG(sp) ) == FAILED ) { deactivate( sp ) ; return( FAILED ) ; } /* * Initialize the service data */ SVC_RUNNING_SERVERS(sp) = SVC_RETRIES(sp) = 0 ; if ( SC_MUST_LISTEN( scp ) ) (void) listen( SVC_FD(sp), LISTEN_BACKLOG ) ; ps.rws.descriptors_free-- ; SVC_STATE(sp) = SVC_ACTIVE ; FD_SET( SVC_FD(sp), &ps.rws.socket_mask ) ; if ( SVC_FD(sp) > ps.rws.mask_max ) ps.rws.mask_max = SVC_FD(sp) ; ps.rws.active_services++ ; ps.rws.available_services++ ; return( OK ) ; }