/* * Steps: * 1. Deactivate the service * 2. Free all memory used by the service and free the service itself * * Since this function may free all memory associated with the service as * well as the memory pointed by sp, only the value of sp should be used * after this call if the return value is 0 (i.e. no dereferencing of sp). * * Special services are never deactivated. */ int svc_release( struct service *sp ) { char *sid = SVC_ID( sp ) ; const char *func = "svc_release" ; if ( SVC_REFCOUNT(sp) == 0 ) { msg( LOG_ERR, func, "%s: svc_release with 0 count", sid ) ; return( 0 ) ; } SVC_REFCOUNT(sp)-- ; if ( SVC_REFCOUNT(sp) == 0 ) { if ( debug.on ) msg( LOG_DEBUG, func, "ref count of service %s dropped to 0", sid ) ; if ( ! SC_IS_SPECIAL( SVC_CONF( sp ) ) ) { if ( SVC_LOG(sp) ) log_end( SC_LOG( SVC_CONF( sp ) ), SVC_LOG(sp) ) ; svc_deactivate( sp ) ; svc_free( sp ) ; sp = NULL; } else /* this shouldn't happen */ msg( LOG_WARNING, func, "ref count of special service %s dropped to 0", sid ) ; return( 0 ) ; } else return( SVC_REFCOUNT(sp) ) ; }
/* * Check for reference counting errors. * Returns number of errors found. * Always set the number of running and retry servers. */ static unsigned refcount_check( struct service *sp, unsigned *running_servers, unsigned *retry_servers ) { char *sid = SVC_ID( sp ) ; unsigned errors = 0 ; int refs ; int refcount = SVC_REFCOUNT( sp ) ; const char *func = "refcount_check" ; if ( refcount <= 0 ) { msg( LOG_ERR, func, "%s service has bad refcount: %d", sid, refcount ) ; errors++ ; } /* * The service table holds a reference to the service. The remaining * references must be from servers and connections. */ refcount-- ; refs = count_refs( sp, SERVERS( ps ), running_servers ) ; if ( ! errors && refs > refcount ) { msg( LOG_ERR, func, "running servers: too many references for %s (%d with max=%d)", sid, refs, refcount ) ; errors++ ; } refs = count_refs( sp, RETRIES( ps ), retry_servers ) ; if ( ! errors && refs > refcount ) { msg( LOG_ERR, func, "retry servers: too many references for %s (%d with max=%d)", sid, refs, refcount ) ; errors++ ; } if ( errors && debug.on ) msg( LOG_DEBUG, func, "%s: %d errors detected", sid, errors ) ; return( errors ) ; }
struct service *svc_make_special( struct service_config *scp ) { struct service *sp ; const char *func = "svc_make_special" ; if ( ( sp = svc_new( scp ) ) == NULL ) { out_of_memory( func ) ; return( NULL ) ; } SVC_NOT_GENERIC(sp) = 1 ; SVC_LOG(sp) = ps.rws.program_log ; SVC_REFCOUNT(sp) = 1 ; SVC_STATE(sp) = SVC_ACTIVE ; return( sp ) ; }