diff --git a/CHANGELOG.md b/CHANGELOG.md index c11282f..3fc70f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - put two timestamps in connection health file; start conn and current - change health file update interval to 240sec - sendMessage to check cloud status == ONLINE before sending +- when killed with SIGTERM, close will use msg in close reason file. ## [1.0.2] - 2019-02-08 - Refactored connection.c and updated corresponding unit tests diff --git a/src/ParodusInternal.c b/src/ParodusInternal.c index d540bca..054f25a 100644 --- a/src/ParodusInternal.c +++ b/src/ParodusInternal.c @@ -131,6 +131,27 @@ char* getWebpaConveyHeader() return NULL; } +int readFromFile(const char *file_name, char **data) +{ + FILE *fp; + int ch_count = 0; + fp = fopen(file_name, "r+"); + if (fp == NULL) + { + ParodusError("Failed to open file %s (errno %d)\n", file_name, errno); + return 0; + } + fseek(fp, 0, SEEK_END); + ch_count = ftell(fp); + fseek(fp, 0, SEEK_SET); + *data = (char *) malloc(sizeof(char) * (ch_count + 1)); + fread(*data, 1, ch_count,fp); + (*data)[ch_count] ='\0'; + fclose(fp); + return 1; +} + + void timespec_diff(struct timespec *start, struct timespec *stop, struct timespec *diff) { diff --git a/src/ParodusInternal.h b/src/ParodusInternal.h index 8d40716..7cc6259 100644 --- a/src/ParodusInternal.h +++ b/src/ParodusInternal.h @@ -157,6 +157,8 @@ char* getWebpaConveyHeader(); void *CRUDHandlerTask(); void addCRUDmsgToQueue(wrp_msg_t *crudMsg); +int readFromFile(const char *file_name, char **data); + void timespec_diff(struct timespec *start, struct timespec *stop, struct timespec *result); diff --git a/src/config.c b/src/config.c index be09283..35b0f5b 100644 --- a/src/config.c +++ b/src/config.c @@ -366,6 +366,7 @@ int parseCommandLine(int argc,char **argv,ParodusCfg * cfg) {"token-server-url", required_argument, 0, 'U'}, {"crud-config-file", required_argument, 0, 'C'}, {"connection-health-file", required_argument, 0, 'S'}, + {"close-reason-file", required_argument, 0, 'R'}, {"mtls-client-key-path", required_argument, 0, 'K'}, {"mtls-client-cert-path", required_argument, 0,'M'}, {0, 0, 0, 0} @@ -384,6 +385,7 @@ int parseCommandLine(int argc,char **argv,ParodusCfg * cfg) parStrncpy (cfg->jwt_key, "", sizeof(cfg->jwt_key)); cfg->crud_config_file = NULL; cfg->connection_health_file = NULL; + cfg->close_reason_file = NULL; cfg->client_cert_path = NULL; cfg->token_server_url = NULL; cfg->cloud_status = NULL; @@ -394,8 +396,9 @@ int parseCommandLine(int argc,char **argv,ParodusCfg * cfg) /* getopt_long stores the option index here. */ int option_index = 0; - c = getopt_long (argc, argv, "m:s:f:d:r:n:b:u:t:o:i:l:p:e:D:j:a:k:c:T:w:J:46:C:S:K:M", - long_options, &option_index); + c = getopt_long (argc, argv, + "m:s:f:d:r:n:b:u:t:o:i:l:p:e:D:j:a:k:c:T:w:J:46:C:S:R:K:M", + long_options, &option_index); /* Detect the end of the options. */ if (c == -1) @@ -538,17 +541,22 @@ int parseCommandLine(int argc,char **argv,ParodusCfg * cfg) ParodusInfo("connection_health_file is %s\n", cfg->connection_health_file); break; + case 'R': + cfg->close_reason_file = strdup(optarg); + ParodusInfo("sigterm_close_reason_file is %s\n", cfg->close_reason_file); + break; + case 'C': cfg->crud_config_file = strdup(optarg); ParodusInfo("crud_config_file is %s\n", cfg->crud_config_file); break; - case 'P': + case 'P': cfg->client_cert_path = strdup(optarg); ParodusInfo("client_cert_path is %s\n", cfg->client_cert_path); break; - case 'U': + case 'U': cfg->token_server_url = strdup(optarg); ParodusInfo("token_server_url is %s\n", cfg->token_server_url); break; @@ -637,6 +645,7 @@ void setDefaultValuesToCfg(ParodusCfg *cfg) ParodusPrint("cfg->webpa_uuid is :%s\n", cfg->webpa_uuid); cfg->crud_config_file = NULL; cfg->connection_health_file = NULL; + cfg->close_reason_file = NULL; cfg->client_cert_path = NULL; cfg->token_server_url = NULL; @@ -797,6 +806,15 @@ void loadParodusCfg(ParodusCfg * config,ParodusCfg *cfg) ParodusPrint("connection_health_file is NULL. set to empty\n"); } + if(config->close_reason_file != NULL) + { + cfg->close_reason_file = strdup(config->close_reason_file); + } + else + { + ParodusPrint("close_reason_file is NULL. set to empty\n"); + } + if(config->crud_config_file != NULL) { cfg->crud_config_file = strdup(config->crud_config_file); diff --git a/src/config.h b/src/config.h index 027068d..4bf5668 100644 --- a/src/config.h +++ b/src/config.h @@ -102,6 +102,7 @@ typedef struct char *client_cert_path; char *token_server_url; char *connection_health_file; + char *close_reason_file; char *mtls_client_key_path; char *mtls_client_cert_path; char *crud_config_file; diff --git a/src/connection.c b/src/connection.c index 07ae9f0..63e97f7 100644 --- a/src/connection.c +++ b/src/connection.c @@ -804,19 +804,37 @@ static noPollConnOpts * createConnOpts (char * extra_headers, bool secure) return opts; } - +static void close_conn ( noPollConn *conn, const char *specified_reason) +{ + const char *effective_reason = specified_reason; + + if (NULL == effective_reason) { + effective_reason = SHUTDOWN_REASON_SYSTEM_RESTART; + } + else if (strcmp (effective_reason, SHUTDOWN_REASON_SIGTERM) == 0) { + char *sigterm_reason; + if (readFromFile (get_parodus_cfg()->close_reason_file, &sigterm_reason) && + (strlen(sigterm_reason) != 0)) + { + nopoll_conn_close_ext(conn, CloseNormalClosure, sigterm_reason, + strlen (sigterm_reason)); + ParodusInfo ("Closed by SIGTERM, reason: %s\n", sigterm_reason); + free (sigterm_reason); + return; + } + /* file could not be read. use canned message. */ + effective_reason = SHUTDOWN_REASON_SYSTEM_RESTART; + ParodusError ("Closed by SIGTERM, but no reason file\n"); + } + nopoll_conn_close_ext(conn, CloseNormalClosure, effective_reason, + strlen (effective_reason)); +} + void close_and_unref_connection(noPollConn *conn) { if (conn) { - const char *reason = get_global_shutdown_reason(); - int reason_len = 0; - int status = CloseNoStatus; - if (NULL != reason) { - reason_len = (int) strlen (reason); - status = CloseNormalClosure; - } + close_conn (conn, get_global_shutdown_reason ()); get_parodus_cfg()->cloud_status = CLOUD_STATUS_OFFLINE; - nopoll_conn_close_ext(conn, status, reason, reason_len); ParodusInfo("cloud_status set as %s after connection close\n", get_parodus_cfg()->cloud_status); } } diff --git a/src/connection.h b/src/connection.h index 3bb049a..e1bcaf9 100644 --- a/src/connection.h +++ b/src/connection.h @@ -35,6 +35,7 @@ extern "C" { /*----------------------------------------------------------------------------*/ #define SHUTDOWN_REASON_PARODUS_STOP "parodus_stopping" #define SHUTDOWN_REASON_SYSTEM_RESTART "system_restarting" +#define SHUTDOWN_REASON_SIGTERM "SIGTERM" /** * parodusOnPingStatusChangeHandler - Function pointer diff --git a/src/crud_internal.c b/src/crud_internal.c index 45459d6..62c9e70 100644 --- a/src/crud_internal.c +++ b/src/crud_internal.c @@ -58,22 +58,7 @@ int writeToJSON(char *data) int readFromJSON(char **data) { - FILE *fp; - int ch_count = 0; - fp = fopen(get_parodus_cfg()->crud_config_file, "r+"); - if (fp == NULL) - { - ParodusError("Failed to open file %s\n", get_parodus_cfg()->crud_config_file); - return 0; - } - fseek(fp, 0, SEEK_END); - ch_count = ftell(fp); - fseek(fp, 0, SEEK_SET); - *data = (char *) malloc(sizeof(char) * (ch_count + 1)); - fread(*data, 1, ch_count,fp); - (*data)[ch_count] ='\0'; - fclose(fp); - return 1; + return readFromFile (get_parodus_cfg()->crud_config_file, data); } /* * @res_obj json object to add it in crud config json file diff --git a/src/main.c b/src/main.c index c7b9d0b..8d26ced 100644 --- a/src/main.c +++ b/src/main.c @@ -137,8 +137,15 @@ static void sig_handler(int sig) } else if ( sig == SIGUSR2 ) { + signal(SIGUSR2, sig_handler); /* reset it to this function */ ParodusInfo("SIGUSR2 received!\n"); } + else if ( sig == SIGTERM ) + { + signal(SIGTERM, sig_handler); /* reset it to this function */ + ParodusInfo("SIGTERM received!\n"); + shutdownSocketConnection(SHUTDOWN_REASON_SIGTERM); + } else if ( sig == SIGCHLD ) { signal(SIGCHLD, sig_handler); /* reset it to this function */ diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 0c594ff..616195f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -224,7 +224,8 @@ target_link_libraries (test_crud_tasks -lcmocka ${PARODUS_COMMON_LIBS} ) # test_crud_internal #------------------------------------------------------------------------------- add_test(NAME test_crud_internal COMMAND ${MEMORY_CHECK} ./test_crud_internal) -add_executable(test_crud_internal test_crud_internal.c ../src/config.c ../src/close_retry.c ../src/string_helpers.c ../src/crud_internal.c ) +add_executable(test_crud_internal test_crud_internal.c ../src/config.c ../src/close_retry.c + ../src/ParodusInternal.c ../src/string_helpers.c ../src/crud_internal.c ) target_link_libraries (test_crud_internal -lcmocka ${PARODUS_COMMON_LIBS} -lcurl -luuid) #------------------------------------------------------------------------------- diff --git a/tests/test_conn_interface.c b/tests/test_conn_interface.c index d553e70..36262d2 100644 --- a/tests/test_conn_interface.c +++ b/tests/test_conn_interface.c @@ -196,6 +196,13 @@ void close_and_unref_connection(noPollConn *conn) function_called(); } +int readFromFile(const char *file_name, char **data) +{ + UNUSED(file_name); + *data = strdup ("parodus_stopping"); + return 1; +} + void nopoll_cleanup_library () { function_called(); diff --git a/tests/test_connection.c b/tests/test_connection.c index bca9dbb..2713241 100644 --- a/tests/test_connection.c +++ b/tests/test_connection.c @@ -111,6 +111,13 @@ pthread_mutex_t *get_interface_down_mut(void) return &interface_down_mut; } +int readFromFile(const char *file_name, char **data) +{ + UNUSED(file_name); + *data = strdup ("parodus_stopping"); + return 1; +} + noPollConn * nopoll_conn_new_opts (noPollCtx * ctx, noPollConnOpts * opts, const char * host_ip, const char * host_port, const char * host_name,const char * get_url,const char * protocols, const char * origin) { UNUSED(host_port); UNUSED(host_name); UNUSED(get_url); UNUSED(protocols); diff --git a/tests/test_crud_internal.c b/tests/test_crud_internal.c index b517de3..465ae76 100644 --- a/tests/test_crud_internal.c +++ b/tests/test_crud_internal.c @@ -35,6 +35,11 @@ bool LastReasonStatus; pthread_mutex_t close_mut; +char *get_global_reconnect_reason() +{ + return "parodus_stopping"; +} + void set_global_reconnect_reason(char *reason) { UNUSED(reason);