// // Copyright (c) 2014 Wind River Systems, Inc. // // SPDX-License-Identifier: Apache-2.0 // #include "sm_service_action.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "sm_types.h" #include "sm_utils.h" #include "sm_debug.h" #include "sm_sha512.h" #include "sm_service_action_table.h" #include "sm_service_action_result_table.h" #define SM_SERVICE_ACTION_MAX_DELAY_IN_SECS 4 #define SM_SERVICE_ACTION_TIMER_SKEW_IN_MS 60000 #define SM_SERVICE_ACTION_VALIDATE_TIMER_IN_MS 60000 // **************************************************************************** // Service Action - Validate // ========================= static void sm_service_action_validate( SmServiceActionDataT* action_data ) { int bytes; FILE* fp; long ms_expired; unsigned char data[2048]; SmSha512HashT hash; SmSha512ContextT context; char plugin_exec[SM_SERVICE_ACTION_PLUGIN_EXEC_MAX_CHAR]; ms_expired = sm_time_get_elapsed_ms( &(action_data->last_hash_validate) ); if( ms_expired < SM_SERVICE_ACTION_VALIDATE_TIMER_IN_MS ) { DPRINTFD( "Not enough time has elapsed, since last validate." ); return; } sm_time_get( &(action_data->last_hash_validate) ); if( 0 == strcmp( SM_SERVICE_ACTION_PLUGIN_TYPE_LSB_SCRIPT, action_data->plugin_type ) ) { snprintf( plugin_exec, sizeof(plugin_exec), "%s/%s", SM_SERVICE_ACTION_PLUGIN_TYPE_LSB_DIR, action_data->plugin_name ); } else if( 0 == strcmp( SM_SERVICE_ACTION_PLUGIN_TYPE_OCF_SCRIPT, action_data->plugin_type ) ) { snprintf( plugin_exec, sizeof(plugin_exec), "%s/%s/%s", SM_SERVICE_ACTION_PLUGIN_TYPE_OCF_PLUGIN_DIR, action_data->plugin_class, action_data->plugin_name ); } else { snprintf( plugin_exec, sizeof(plugin_exec), "%s", action_data->plugin_name ); } fp = fopen( plugin_exec, "rb" ); if( NULL == fp ) { DPRINTFE( "Failed to open file (%s).", plugin_exec ); return; } sm_sha512_initialize( &context ); while( 0 != (bytes = fread( data, 1, 2048, fp )) ) { sm_sha512_update( &context, data, bytes ); } sm_sha512_finalize( &context, &hash ); if( 0 != memcmp( &(action_data->hash.bytes[0]), &(hash.bytes[0]), SM_SHA512_HASH_SIZE ) ) { char was_hash_str[SM_SHA512_HASH_STR_SIZE]; char now_hash_str[SM_SHA512_HASH_STR_SIZE]; sm_sha512_hash_str( was_hash_str, &(action_data->hash) ); sm_sha512_hash_str( now_hash_str, &hash ); DPRINTFI( "Plugin (%s) has been changed, was=%s, now=%s.", plugin_exec, was_hash_str, now_hash_str ); memcpy( &(action_data->hash), &hash, sizeof(hash) ); } fclose( fp ); } // **************************************************************************** // **************************************************************************** // Service Action - Exist // ====================== SmErrorT sm_service_action_exist( char service_name[], SmServiceActionT action ) { SmServiceActionDataT* action_data; action_data = sm_service_action_table_read( service_name, action ); if( NULL == action_data ) { DPRINTFD( "Service (%s) action (%s) does not exist.", service_name, sm_service_action_str( action ) ); return( SM_NOT_FOUND ); } return( SM_OKAY ); } // **************************************************************************** // **************************************************************************** // Service Action - Interval // ========================= SmErrorT sm_service_action_interval( char service_name[], SmServiceActionT action, int* interval_in_ms ) { SmServiceActionDataT* action_data; *interval_in_ms = 0; action_data = sm_service_action_table_read( service_name, action ); if( NULL == action_data ) { DPRINTFD( "Service (%s) action (%s) does not exist.", service_name, sm_service_action_str( action ) ); return( SM_NOT_FOUND ); } *interval_in_ms = action_data->interval_in_secs * 1000; return( SM_OKAY ); } // **************************************************************************** // **************************************************************************** // Service Action - Maximum Retries // ================================ SmErrorT sm_service_action_max_retries( char service_name[], SmServiceActionT action, int* max_failure_retries, int* max_timeout_retries, int* max_total_retries ) { SmServiceActionDataT* action_data; *max_failure_retries = 0; *max_timeout_retries = 0; *max_total_retries = 0; action_data = sm_service_action_table_read( service_name, action ); if( NULL == action_data ) { DPRINTFD( "Service (%s) action (%s) does not exist.", service_name, sm_service_action_str( action ) ); return( SM_NOT_FOUND ); } *max_failure_retries = action_data->max_failure_retries; *max_timeout_retries = action_data->max_timeout_retries; *max_total_retries = action_data->max_total_retries; return( SM_OKAY ); } // **************************************************************************** // **************************************************************************** // Service Action - Plugin Result // ============================== static SmErrorT sm_service_action_plugin_result( char service_name[], SmServiceActionT action, char plugin_type[], char plugin_name[], char plugin_command[], char plugin_exit_code[], SmServiceActionResultDataT** action_result ) { char plugin_command_default[] = "default"; char plugin_exit_code_other[] = "other"; // Map the plugin result to an action result with the given data. *action_result = sm_service_action_result_table_read( plugin_type, plugin_name, plugin_command, plugin_exit_code ); if( NULL != *action_result ) { DPRINTFD( "Read service (%s) action (%s) plugin (%s, %s, %s, %s) data.", service_name, sm_service_action_str( action ), plugin_type, plugin_name, plugin_command, plugin_exit_code ); return( SM_OKAY ); } // Map the plugin result to an action result with the plugin exit // code set to "other". *action_result = sm_service_action_result_table_read( plugin_type, plugin_name, plugin_command, plugin_exit_code_other ); if( NULL != *action_result ) { DPRINTFD( "Read service (%s) action (%s) plugin (%s, %s, %s, other) " "data.", service_name, sm_service_action_str( action ), plugin_type, plugin_name, plugin_command ); return( SM_OKAY ); } // Map the plugin result to an action result with the plugin command // set to "default". *action_result = sm_service_action_result_table_read( plugin_type, plugin_name, plugin_command_default, plugin_exit_code ); if( NULL != *action_result ) { DPRINTFD( "Read service (%s) action (%s) plugin (%s, %s, default, %s) " "data.", service_name, sm_service_action_str( action ), plugin_type, plugin_name, plugin_exit_code ); return( SM_OKAY ); } // Map the plugin result to an action result with the plugin // command set to "default" and the plugin exit code set to "other". *action_result = sm_service_action_result_table_read( plugin_type, plugin_name, plugin_command_default, plugin_exit_code_other ); if( NULL != *action_result ) { DPRINTFD( "Read service (%s) action (%s) plugin " "(%s, %s, default, other) data.", service_name, sm_service_action_str( action ), plugin_type, plugin_name ); return( SM_OKAY ); } return( SM_NOT_FOUND ); } // **************************************************************************** // **************************************************************************** // Service Action - Result // ======================= SmErrorT sm_service_action_result( int exit_code, char service_name[], SmServiceActionT action, SmServiceActionResultT* action_result, SmServiceStateT* service_state, SmServiceStatusT* service_status, SmServiceConditionT* service_condition, char reason_text[] ) { char plugin_name_default[] = "default"; char plugin_exit_code[SM_SERVICE_ACTION_PLUGIN_EXIT_CODE_MAX_CHAR]; SmServiceActionDataT* action_data; SmServiceActionResultDataT* result; SmErrorT error; reason_text[0] = '\0'; if( SM_SERVICE_ACTION_PLUGIN_FAILURE == exit_code ) { snprintf( plugin_exit_code, sizeof(plugin_exit_code), "plugin-failure" ); } else if( SM_SERVICE_ACTION_PLUGIN_TIMEOUT == exit_code ) { snprintf( plugin_exit_code, sizeof(plugin_exit_code), "plugin-timeout" ); } else { snprintf( plugin_exit_code, sizeof(plugin_exit_code), "%i", exit_code ); } *action_result = SM_SERVICE_ACTION_RESULT_UNKNOWN; *service_state = SM_SERVICE_STATE_UNKNOWN; *service_status = SM_SERVICE_STATUS_UNKNOWN; *service_condition = SM_SERVICE_CONDITION_UNKNOWN; action_data = sm_service_action_table_read( service_name, action ); if( NULL == action_data ) { DPRINTFD( "Service (%s) action (%s) does not exist.", service_name, sm_service_action_str( action ) ); return( SM_NOT_FOUND ); } error = sm_service_action_plugin_result( service_name, action, action_data->plugin_type, action_data->plugin_name, action_data->plugin_command, plugin_exit_code, &result ); if( SM_OKAY == error ) { *action_result = result->action_result; *service_state = result->service_state; *service_status = result->service_status; *service_condition = result->service_condition; return( SM_OKAY ); } else if(( SM_OKAY != error )&&( SM_NOT_FOUND != error )) { DPRINTFE( "Failed to read service (%s) action (%s) plugin result " "data, error=%s.", service_name, sm_service_action_str( action ), sm_error_str( error ) ); return( error ); } error = sm_service_action_plugin_result( service_name, action, action_data->plugin_type, plugin_name_default, action_data->plugin_command, plugin_exit_code, &result ); if( SM_OKAY != error ) { DPRINTFE( "Failed to read service (%s) action (%s) plugin result " "data, error=%s.", service_name, sm_service_action_str( action ), sm_error_str( error ) ); return( error ); } *action_result = result->action_result; *service_state = result->service_state; *service_status = result->service_status; *service_condition = result->service_condition; return( SM_OKAY ); } // **************************************************************************** // **************************************************************************** // Service Action - Abort // ====================== SmErrorT sm_service_action_abort( char service_name[], int process_id ) { // //TODO: Verify the process we are about to abort is the process we expect. // if( -1 == process_id ) { DPRINTFE( "Trying to abort a process (%i) for service (%s), " "but pid is invalid.", process_id, service_name ); return( SM_FAILED ); } if( process_id == (int) getpid() ) { DPRINTFE( "Trying to abort a process (%i) for service (%s), " "but pid is self.", process_id, service_name ); return( SM_FAILED ); } DPRINTFI( "Aborting service (%s) with kill signal, pid=%i.", service_name, process_id ); if( 0 > kill( process_id, SIGKILL ) ) { if( ESRCH == errno ) { DPRINTFD( "Service (%s) action not running.", service_name ); return( SM_OKAY ); } else { DPRINTFE( "Failed to send kill signal to service (%s), " "error=%s.", service_name, strerror( errno ) ); return( SM_FAILED ); } } DPRINTFD( "Kill signal sent to service (%s).", service_name ); return( SM_OKAY ); } // **************************************************************************** // **************************************************************************** // Service Action - Setup Instance Environment Variables // ===================================================== static SmErrorT sm_service_action_setup_instance_env_vars( char instance_name[], char instance_params[], SmServiceActionDataT* action_data ) { char looking_for = '='; char key_storage[SM_SERVICE_INSTANCE_PARAMS_MAX_CHAR+32]; char value_storage[SM_SERVICE_INSTANCE_PARAMS_MAX_CHAR+32]; char* key = NULL; char* value = NULL; char* param = NULL; if( 0 == strcmp( SM_SERVICE_ACTION_PLUGIN_TYPE_OCF_SCRIPT, action_data->plugin_type ) ) { if( 0 > setenv( "OCF_RA_VERSION_MAJOR", SM_SERVICE_ACTION_PLUGIN_TYPE_OCF_VERSION, 1 ) ) { DPRINTFE( "Failed to set environment variable " "(OCF_RA_VERSION_MAJOR), error=%s.", strerror( errno ) ); goto ERROR; } if( 0 > setenv( "OCF_RA_VERSION_MINOR", SM_SERVICE_ACTION_PLUGIN_TYPE_OCF_REVISION, 1 ) ) { DPRINTFE( "Failed to set environment variable " "(OCF_RA_VERSION_MINOR), error=%s.", strerror( errno ) ); goto ERROR; } if( 0 > setenv( "OCF_ROOT", SM_SERVICE_ACTION_PLUGIN_TYPE_OCF_DIR, 1 ) ) { DPRINTFE( "Failed to set environment variable " "(OCF_ROOT), error=%s.", strerror( errno ) ); goto ERROR; } if( 0 > setenv( "OCF_RESOURCE_INSTANCE", instance_name, 1 ) ) { DPRINTFE( "Failed to set environment variable " "(OCF_RESOURCE_INSTANCE), error=%s.", strerror( errno ) ); goto ERROR; } if( 0 > setenv( "OCF_RESOURCE_TYPE", action_data->plugin_name, 1 ) ) { DPRINTFE( "Failed to set environment variable " "(OCF_RESOURCE_TYPE), error=%s.", strerror( errno ) ); goto ERROR; } } param = &(value_storage[sizeof(value_storage)-1]); *param = '\0'; --param; int char_i; for( char_i=strlen(instance_params)-1; 0 <= char_i; --char_i ) { if( looking_for == instance_params[char_i] ) { if( ',' == looking_for ) { key = param+1; if( 0 == strcmp( SM_SERVICE_ACTION_PLUGIN_TYPE_OCF_SCRIPT, action_data->plugin_type ) ) { key -= strlen("OCF_RESKEY_"); memcpy( key, "OCF_RESKEY_", strlen("OCF_RESKEY_") ); } DPRINTFD( "%s set environment: %s=%s", instance_name, key, value ); if( 0 > setenv( key, value, 1 ) ) { DPRINTFE( "Failed to set environment variable (%s=%s), " "error=%s.", key, value, strerror( errno ) ); goto ERROR; } key = NULL; value = NULL; param = &(value_storage[sizeof(value_storage)-1]); *param = '\0'; --param; looking_for = '='; } else { key = NULL; value = param+1; param = &(key_storage[sizeof(key_storage)-1]); *param = '\0'; --param; looking_for = ','; } } else { *param = instance_params[char_i]; --param; } } if( NULL != value ) { key = param+1; if( 0 == strcmp( SM_SERVICE_ACTION_PLUGIN_TYPE_OCF_SCRIPT, action_data->plugin_type ) ) { key -= strlen("OCF_RESKEY_"); memcpy( key, "OCF_RESKEY_", strlen("OCF_RESKEY_") ); } DPRINTFD( "%s set environment: %s=%s", instance_name, key, value ); if( 0 > setenv( key, value, 1 ) ) { DPRINTFE( "Failed to set environment variable (%s=%s), " "error=%s.", key, value, strerror( errno ) ); goto ERROR; } } return( SM_OKAY ); ERROR: return( SM_FAILED ); } // **************************************************************************** // **************************************************************************** // Service Action - Setup Plugin Environment Variables // =================================================== static SmErrorT sm_service_action_setup_plugin_env_vars( SmServiceActionDataT* action_data ) { char looking_for = '='; char key_storage[SM_SERVICE_ACTION_PLUGIN_PARAMS_MAX_CHAR+32]; char value_storage[SM_SERVICE_ACTION_PLUGIN_PARAMS_MAX_CHAR+32]; char* key = NULL; char* value = NULL; char* param = NULL; if( 0 == strcmp( SM_SERVICE_ACTION_PLUGIN_TYPE_LSB_SCRIPT, action_data->plugin_type ) ) { if( 0 > setenv( "SYSTEMCTL_SKIP_REDIRECT", "1", 1 ) ) { DPRINTFE( "Failed to set environment variable " "(SYSTEMCTL_SKIP_REDIRECT), error=%s.", strerror( errno ) ); goto ERROR; } } else if( 0 == strcmp( SM_SERVICE_ACTION_PLUGIN_TYPE_OCF_SCRIPT, action_data->plugin_type ) ) { if( 0 > setenv( "HA_LOGFACILITY", "daemon", 1 ) ) { DPRINTFE( "Failed to set environment variable (HA_LOGFACILITY), " "error=%s.", strerror( errno ) ); goto ERROR; } } param = &(value_storage[sizeof(value_storage)-1]); *param = '\0'; --param; int char_i; for( char_i=strlen(action_data->plugin_params)-1; 0 <= char_i; --char_i ) { if( looking_for == action_data->plugin_params[char_i] ) { if( ',' == looking_for ) { key = param+1; if( 0 == strcmp( SM_SERVICE_ACTION_PLUGIN_TYPE_OCF_SCRIPT, action_data->plugin_type ) ) { key -= strlen("OCF_RESKEY_CRM_meta_"); memcpy( key, "OCF_RESKEY_CRM_meta_", strlen("OCF_RESKEY_CRM_meta_") ); } DPRINTFD( "%s set environment: %s=%s", action_data->service_name, key, value ); if( 0 > setenv( key, value, 1 ) ) { DPRINTFE( "Failed to set environment variable (%s=%s), " "error=%s.", key, value, strerror( errno ) ); goto ERROR; } param = &(value_storage[sizeof(value_storage)-1]); *param = '\0'; --param; looking_for = '='; } else { value = param+1; param = &(key_storage[sizeof(key_storage)-1]); *param = '\0'; --param; looking_for = ','; } } else { *param = action_data->plugin_params[char_i]; --param; } } if( NULL != value ) { key = param+1; if( 0 == strcmp( SM_SERVICE_ACTION_PLUGIN_TYPE_OCF_SCRIPT, action_data->plugin_type ) ) { key -= strlen("OCF_RESKEY_CRM_meta_"); memcpy( key, "OCF_RESKEY_CRM_meta_", strlen("OCF_RESKEY_CRM_meta_") ); } DPRINTFD( "%s set environment: %s=%s", action_data->service_name, key, value ); if( 0 > setenv( key, value, 1 ) ) { DPRINTFE( "Failed to set environment variable (%s=%s), " "error=%s.", key, value, strerror( errno ) ); goto ERROR; } } return( SM_OKAY ); ERROR: return( SM_FAILED ); } // **************************************************************************** // **************************************************************************** // Service Action - Setup Environment // ================================== static SmErrorT sm_service_action_setup_env( char instance_name[], char instance_params[], SmServiceActionDataT* action_data ) { SmErrorT error; error = sm_service_action_setup_instance_env_vars( instance_name, instance_params, action_data ); if( SM_OKAY != error ) { DPRINTFE( "Failed to set instance environment variables for service " "(%s) action (%s), error=%s.", action_data->service_name, sm_service_action_str( action_data->action ), sm_error_str( error ) ); return( error ); } error = sm_service_action_setup_plugin_env_vars( action_data ); if( SM_OKAY != error ) { DPRINTFE( "Failed to set plugin environment variables for service " "(%s) action (%s), error=%s.", action_data->service_name, sm_service_action_str( action_data->action ), sm_error_str( error ) ); return( error ); } return( SM_OKAY ); } // **************************************************************************** // **************************************************************************** // Service Action - Run // ==================== SmErrorT sm_service_action_run( char service_name[], char instance_name[], char instance_params[], SmServiceActionT action, int* process_id, int* timeout_in_ms ) { pid_t pid; bool service_managed = true; struct stat stat_data; char plugin_exec[SM_SERVICE_ACTION_PLUGIN_EXEC_MAX_CHAR]; int result; SmServiceActionDataT* action_data; SmErrorT error; *process_id = -1; *timeout_in_ms = 0; action_data = sm_service_action_table_read( service_name, action ); if( NULL == action_data ) { DPRINTFD( "Service (%s) action (%s) does not exist.", service_name, sm_service_action_str( action ) ); return( SM_NOT_FOUND ); } snprintf( plugin_exec, sizeof(plugin_exec), "%s/%s.unmanaged", SM_RUN_SERVICES_DIRECTORY, service_name ); if( 0 == access( plugin_exec, F_OK ) ) { DPRINTFI( "Service (%s) is unmanaged, actions are force-passed.", service_name ); service_managed = false; } if( service_managed ) { sm_service_action_validate( action_data ); if( 0 == strcmp( SM_SERVICE_ACTION_PLUGIN_TYPE_LSB_SCRIPT, action_data->plugin_type ) ) { snprintf( plugin_exec, sizeof(plugin_exec), "%s/%s", SM_SERVICE_ACTION_PLUGIN_TYPE_LSB_DIR, action_data->plugin_name ); } else if( 0 == strcmp( SM_SERVICE_ACTION_PLUGIN_TYPE_OCF_SCRIPT, action_data->plugin_type ) ) { snprintf( plugin_exec, sizeof(plugin_exec), "%s/%s/%s", SM_SERVICE_ACTION_PLUGIN_TYPE_OCF_PLUGIN_DIR, action_data->plugin_class, action_data->plugin_name ); } else { snprintf( plugin_exec, sizeof(plugin_exec), "%s", action_data->plugin_name ); } DPRINTFD( "Plugin executable (%s) for service (%s).", plugin_exec, action_data->service_name ); if( 0 > access( plugin_exec, F_OK | X_OK ) ) { DPRINTFE( "Service (%s) plugin (%s) access failed, error=%s.", action_data->service_name, plugin_exec, strerror( errno ) ); return( SM_FAILED ); } if( 0 > stat( plugin_exec, &stat_data ) ) { DPRINTFE( "Service (%s) plugin (%s) stat failed, error=%s.", action_data->service_name, plugin_exec, strerror( errno ) ); return( SM_FAILED ); } if( 0 >= stat_data.st_size ) { DPRINTFE( "Service (%s) plugin (%s) has zero size.", action_data->service_name, action_data->plugin_name ); return( SM_FAILED ); } } pid = fork(); if( 0 > pid ) { DPRINTFE( "Failed to fork process for service (%s), error=%s.", action_data->service_name, strerror( errno ) ); return( SM_FAILED ); } else if( 0 == pid ) { // Child process. struct rlimit file_limits; DPRINTFD( "Child process created for service (%s).", action_data->service_name ); if( 0 > setpgid( 0, 0 ) ) { DPRINTFE( "Failed to set process group id for service (%s), " "error=%s.", action_data->service_name, strerror( errno ) ); exit( SM_SERVICE_ACTION_PLUGIN_FAILURE ); } if( 0 > getrlimit( RLIMIT_NOFILE, &file_limits ) ) { DPRINTFE( "Failed to get file limits for service (%s), " "error=%s.", action_data->service_name, strerror( errno ) ); exit( SM_SERVICE_ACTION_PLUGIN_FAILURE ); } unsigned int fd_i; for( fd_i=0; fd_i < file_limits.rlim_cur; ++fd_i ) { close( fd_i ); } if( 0 > open( "/dev/null", O_RDONLY ) ) { DPRINTFE( "Failed to open stdin to /dev/null for service (%s), " "error=%s.", action_data->service_name, strerror( errno ) ); } if( 0 > open( "/dev/null", O_WRONLY ) ) { DPRINTFE( "Failed to open stdout to /dev/null for service (%s), " "error=%s.", action_data->service_name, strerror( errno ) ); } if( 0 > open( "/dev/null", O_WRONLY ) ) { DPRINTFE( "Failed to open stderr to /dev/null for service (%s), " "error=%s.", action_data->service_name, strerror( errno ) ); } result = setpriority( PRIO_PROCESS, getpid(), -1 ); if( 0 > result ) { DPRINTFE( "Failed to set priority of process, error=%s.", strerror( errno ) ); exit( SM_SERVICE_ACTION_PLUGIN_FAILURE ); } if( !service_managed ) { exit( SM_SERVICE_ACTION_PLUGIN_FORCE_SUCCESS ); } error = sm_service_action_setup_env( instance_name, instance_params, action_data ); if( SM_OKAY != error ) { DPRINTFE( "Failed to setup environment for service (%s), " "error=%s.", action_data->service_name, sm_error_str( error ) ); exit( SM_SERVICE_ACTION_PLUGIN_FAILURE ); } #ifdef SM_SERVICE_ACTION_TIME_PLUGIN char time_exec[] = "/usr/bin/time"; char time_append[] = "-a"; char time_output[] = "-o"; char time_file[80]; char* argv[] = {time_exec, time_append, time_output, time_file, plugin_exec, action_data->plugin_command, NULL}; snprintf( time_file, sizeof(time_file), "/tmp/%s_%s-timing.txt", action_data->service_name, action_data->plugin_command ); if( 0 > execv( time_exec, argv ) ) { DPRINTFE( "Failed to exec command for service (%s), " "error=%s.", action_data->service_name, strerror( errno ) ); } #else char* argv[] = {plugin_exec, action_data->plugin_command, NULL}; if( 0 > execv( plugin_exec, argv ) ) { DPRINTFE( "Failed to exec command for service (%s), " "error=%s.", action_data->service_name, strerror( errno ) ); } #endif // SM_SERVICE_ACTION_TIME_PLUGIN exit( SM_SERVICE_ACTION_PLUGIN_FAILURE ); } else { // Parent process. *process_id = (int) pid; *timeout_in_ms = action_data->timeout_in_secs * 1000; if( sm_utils_watchdog_delayed( SM_SERVICE_ACTION_MAX_DELAY_IN_SECS ) ) { DPRINTFI( "Service (%s) timeout %d secs increased by %d ms, " "sm-watchdog delayed.", action_data->service_name, action_data->timeout_in_secs, SM_SERVICE_ACTION_TIMER_SKEW_IN_MS ); *timeout_in_ms += SM_SERVICE_ACTION_TIMER_SKEW_IN_MS; } DPRINTFD( "Child process (%i) created for service (%s).", *process_id, action_data->service_name ); } return( SM_OKAY ); } // **************************************************************************** // **************************************************************************** // Service Action - Initialize // =========================== SmErrorT sm_service_action_initialize( void ) { SmErrorT error; error = sm_service_action_table_initialize(); if( SM_OKAY != error ) { DPRINTFE( "Failed to initialize service action table, error=%s.", sm_error_str( error ) ); return( error ); } error = sm_service_action_result_table_initialize(); if( SM_OKAY != error ) { DPRINTFE( "Failed to initialize service action result table, " "error=%s.", sm_error_str( error ) ); return( error ); } return( SM_OKAY ); } // **************************************************************************** // **************************************************************************** // Service Action - Finalize // ========================= SmErrorT sm_service_action_finalize( void ) { SmErrorT error; error = sm_service_action_result_table_finalize(); if( SM_OKAY != error ) { DPRINTFE( "Failed to finalize service action result table, error=%s.", sm_error_str( error ) ); } error = sm_service_action_table_finalize(); if( SM_OKAY != error ) { DPRINTFE( "Failed to finalize service action table, error=%s.", sm_error_str( error ) ); } return( SM_OKAY ); } // ****************************************************************************