diff options
Diffstat (limited to 'src/lib/dlt_user.c')
-rw-r--r-- | src/lib/dlt_user.c | 311 |
1 files changed, 198 insertions, 113 deletions
diff --git a/src/lib/dlt_user.c b/src/lib/dlt_user.c index 99df11b..0397e48 100644 --- a/src/lib/dlt_user.c +++ b/src/lib/dlt_user.c @@ -85,14 +85,22 @@ int *p = NULL; \ *p = 0; \ } \ - } while (0) + } while (false) #else /* DLT_FATAL_LOG_RESET_ENABLE */ # define DLT_LOG_FATAL_RESET_TRAP(LOGLEVEL) #endif /* DLT_FATAL_LOG_RESET_ENABLE */ +enum InitState { + INIT_UNITIALIZED, + INIT_IN_PROGRESS, + INIT_DONE +}; + static DltUser dlt_user; -static atomic_bool dlt_user_initialised = false; -static int dlt_user_freeing = 0; +static _Atomic enum InitState dlt_user_init_state = INIT_UNITIALIZED; +#define DLT_USER_INITALIZED (dlt_user_init_state == INIT_DONE) + +static _Atomic int dlt_user_freeing = 0; static bool dlt_user_file_reach_max = false; #ifdef DLT_LIB_USE_FIFO_IPC @@ -103,6 +111,10 @@ static char dlt_daemon_fifo[DLT_PATH_MAX]; static sem_t dlt_mutex; static pthread_t dlt_housekeeperthread_handle; +/* Sync housekeeper thread start */ +pthread_mutex_t dlt_housekeeper_running_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t dlt_housekeeper_running_cond; + /* calling dlt_user_atexit_handler() second time fails with error message */ static int atexit_registered = 0; @@ -209,7 +221,7 @@ static void dlt_user_trace_network_segmented_thread_segmenter(s_segmented_data * #endif static DltReturnValue dlt_user_log_write_string_utils_attr(DltContextData *log, const char *text, const enum StringType type, const char *name, bool with_var_info); -static DltReturnValue dlt_user_log_write_sized_string_utils_attr(DltContextData *log, const char *text, uint16_t length, const enum StringType type, const char *name, bool with_var_info); +static DltReturnValue dlt_user_log_write_sized_string_utils_attr(DltContextData *log, const char *text, size_t length, const enum StringType type, const char *name, bool with_var_info); static DltReturnValue dlt_unregister_app_util(bool force_sending_messages); @@ -308,7 +320,7 @@ static DltReturnValue dlt_initialize_socket_connection(void) sockfd, DLT_RECEIVE_SOCKET, DLT_USER_RCVBUF_MAX_SIZE) == DLT_RETURN_ERROR) { - dlt_user_initialised = false; + dlt_user_init_state = INIT_UNITIALIZED; close(sockfd); DLT_SEM_FREE(); return DLT_RETURN_ERROR; @@ -363,7 +375,7 @@ static DltReturnValue dlt_initialize_vsock_connection() sockfd, DLT_RECEIVE_SOCKET, DLT_USER_RCVBUF_MAX_SIZE) == DLT_RETURN_ERROR) { - dlt_user_initialised = false; + dlt_user_init_state = INIT_UNITIALIZED; close(sockfd); DLT_SEM_FREE(); return DLT_RETURN_ERROR; @@ -445,35 +457,37 @@ static DltReturnValue dlt_initialize_fifo_connection(void) DltReturnValue dlt_init(void) { - /* Compare 'dlt_user_initialised' to false. If equal, 'dlt_user_initialised' will be set to true. - Calls retruns true, if 'dlt_user_initialised' was false. - That way it's no problem, if two threads enter this function, because only the very first one will - pass fully. The other one will immediately return, because when it executes the atomic function - 'dlt_user_initialised' will be for sure already set to true. - */ - bool expected = false; - if (!(atomic_compare_exchange_strong(&dlt_user_initialised, &expected, true))) + /* process is exiting. Do not allocate new resources. */ + if (dlt_user_freeing != 0) { + dlt_vlog(LOG_INFO, "%s logging disabled, process is exiting\n", __func__); + /* return negative value, to stop the current log */ + return DLT_RETURN_LOGGING_DISABLED; + } + + /* Compare dlt_user_init_state to INIT_UNITIALIZED. If equal it will be set to INIT_IN_PROGRESS. + * Call returns DLT_RETURN_OK init state != INIT_UNITIALIZED + * That way it's no problem, if two threads enter this function, because only the very first one will + * pass fully. The other one will immediately return, because when it executes the atomic function + * dlt_user_init_state won't be INIT_UNITIALIZED anymore. + * This is not handled via a simple boolean to prevent issues with shutting down while the init is still running. + * Furthermore, this makes sure we enter some function only when dlt_init is fully done. + * */ + enum InitState expectedInitState = INIT_UNITIALIZED; + if (!(atomic_compare_exchange_strong(&dlt_user_init_state, &expectedInitState, INIT_IN_PROGRESS))) { return DLT_RETURN_OK; + } /* check environment variables */ dlt_check_envvar(); /* Check logging mode and internal log file is opened or not*/ - if(logging_mode == DLT_LOG_TO_FILE && logging_handle == NULL) - { + if (logging_mode == DLT_LOG_TO_FILE && logging_handle == NULL) { dlt_log_init(logging_mode); } - /* process is exiting. Do not allocate new resources. */ - if (dlt_user_freeing != 0) { - dlt_vlog(LOG_INFO, "%s logging disabled, process is exiting", __func__); - /* return negative value, to stop the current log */ - return DLT_RETURN_LOGGING_DISABLED; - } - /* Initialize common part of dlt_init()/dlt_init_file() */ if (dlt_init_common() == DLT_RETURN_ERROR) { - dlt_user_initialised = false; + dlt_user_init_state = INIT_UNITIALIZED; return DLT_RETURN_ERROR; } @@ -515,7 +529,7 @@ DltReturnValue dlt_init(void) dlt_user.dlt_user_handle, DLT_RECEIVE_FD, DLT_USER_RCVBUF_MAX_SIZE) == DLT_RETURN_ERROR) { - dlt_user_initialised = false; + dlt_user_init_state = INIT_UNITIALIZED; return DLT_RETURN_ERROR; } @@ -530,13 +544,18 @@ DltReturnValue dlt_init(void) #endif if (dlt_start_threads() < 0) { - dlt_user_initialised = false; + dlt_user_init_state = INIT_UNITIALIZED; return DLT_RETURN_ERROR; } /* prepare for fork() call */ pthread_atfork(NULL, NULL, &dlt_fork_child_fork_handler); + expectedInitState = INIT_IN_PROGRESS; + if (!(atomic_compare_exchange_strong(&dlt_user_init_state, &expectedInitState, INIT_DONE))) { + return DLT_RETURN_ERROR; + } + return DLT_RETURN_OK; } @@ -557,19 +576,21 @@ DltReturnValue dlt_init_file(const char *name) if (!name) return DLT_RETURN_WRONG_PARAMETER; - /* Compare 'dlt_user_initialised' to false. If equal, 'dlt_user_initialised' will be set to true. - Calls retruns true, if 'dlt_user_initialised' was false. - That way it's no problem, if two threads enter this function, because only the very first one will - pass fully. The other one will immediately return, because when it executes the atomic function - 'dlt_user_initialised' will be for sure already set to true. - */ - bool expected = false; - if (!(atomic_compare_exchange_strong(&dlt_user_initialised, &expected, true))) + /* Compare dlt_user_init_state to INIT_UNITIALIZED. If equal it will be set to INIT_IN_PROGRESS. + * Call returns DLT_RETURN_OK init state != INIT_UNITIALIZED + * That way it's no problem, if two threads enter this function, because only the very first one will + * pass fully. The other one will immediately return, because when it executes the atomic function + * dlt_user_init_state won't be INIT_UNITIALIZED anymore. + * This is not handled via a simple boolean to prevent issues with shutting down while the init is still running. + * Furthermore, this makes sure we enter some function only when dlt_init is fully done. + * */ + enum InitState expectedInitState = INIT_UNITIALIZED; + if (!(atomic_compare_exchange_strong(&dlt_user_init_state, &expectedInitState, INIT_IN_PROGRESS))) return DLT_RETURN_OK; /* Initialize common part of dlt_init()/dlt_init_file() */ if (dlt_init_common() == DLT_RETURN_ERROR) { - dlt_user_initialised = false; + expectedInitState = INIT_UNITIALIZED; return DLT_RETURN_ERROR; } @@ -699,7 +720,7 @@ DltReturnValue dlt_init_common(void) /* Binary semaphore for threads */ if (sem_init(&dlt_mutex, 0, 1) == -1) { - dlt_user_initialised = false; + dlt_user_init_state = INIT_UNITIALIZED; return DLT_RETURN_ERROR; } @@ -846,7 +867,7 @@ DltReturnValue dlt_init_common(void) (dlt_user.log_buf_len + header_size)); if (dlt_user.resend_buffer == NULL) { - dlt_user_initialised = false; + dlt_user_init_state = INIT_UNITIALIZED; DLT_SEM_FREE(); dlt_vlog(LOG_ERR, "cannot allocate memory for resend buffer\n"); return DLT_RETURN_ERROR; @@ -863,7 +884,7 @@ DltReturnValue dlt_init_common(void) buffer_min, buffer_max, buffer_step) == DLT_RETURN_ERROR) { - dlt_user_initialised = false; + dlt_user_init_state = INIT_UNITIALIZED; DLT_SEM_FREE(); return DLT_RETURN_ERROR; } @@ -892,8 +913,8 @@ void dlt_user_atexit_handler(void) if (g_dlt_is_child) return; - if (!dlt_user_initialised) { - dlt_vlog(LOG_WARNING, "%s dlt_user_initialised false\n", __FUNCTION__); + if (!DLT_USER_INITALIZED) { + dlt_vlog(LOG_WARNING, "%s dlt_user_init_state != INIT_DONE\n", __FUNCTION__); /* close file */ dlt_log_free(); return; @@ -981,26 +1002,26 @@ DltReturnValue dlt_free(void) { uint32_t i; int ret = 0; + int expected = 0; #ifdef DLT_LIB_USE_FIFO_IPC char filename[DLT_PATH_MAX]; #endif - if (dlt_user_freeing != 0) + /* library is freeing its resources. Avoid to allocate it in dlt_init() */ + if (!(atomic_compare_exchange_strong(&dlt_user_freeing, &expected, 1))) { /* resources are already being freed. Do nothing and return. */ return DLT_RETURN_ERROR; + } - /* library is freeing its resources. Avoid to allocate it in dlt_init() */ - dlt_user_freeing = 1; - - if (!dlt_user_initialised) { + if (!DLT_USER_INITALIZED) { dlt_user_freeing = 0; return DLT_RETURN_ERROR; } - dlt_user_initialised = false; - dlt_stop_threads(); + dlt_user_init_state = INIT_UNITIALIZED; + #ifdef DLT_LIB_USE_FIFO_IPC if (dlt_user.dlt_user_handle != DLT_FD_INIT) { @@ -1184,7 +1205,7 @@ DltReturnValue dlt_register_app(const char *apid, const char *description) if (g_dlt_is_child) return DLT_RETURN_ERROR; - if (!dlt_user_initialised) { + if (!DLT_USER_INITALIZED) { if (dlt_init() < 0) { dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__); return DLT_RETURN_ERROR; @@ -1263,7 +1284,7 @@ DltReturnValue dlt_register_context(DltContext *handle, const char *contextid, c if (g_dlt_is_child) return DLT_RETURN_ERROR; - if (!dlt_user_initialised) { + if (!DLT_USER_INITALIZED) { if (dlt_init() < 0) { dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__); return DLT_RETURN_ERROR; @@ -1512,7 +1533,7 @@ DltReturnValue dlt_register_context_llccb(DltContext *handle, if (g_dlt_is_child) return DLT_RETURN_ERROR; - if (!dlt_user_initialised) { + if (!DLT_USER_INITALIZED) { if (dlt_init() < 0) { dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__); return DLT_RETURN_ERROR; @@ -1537,8 +1558,8 @@ DltReturnValue dlt_unregister_app_util(bool force_sending_messages) if (g_dlt_is_child) return DLT_RETURN_ERROR; - if (!dlt_user_initialised) { - dlt_vlog(LOG_WARNING, "%s dlt_user_initialised false\n", __FUNCTION__); + if (!DLT_USER_INITALIZED) { + dlt_vlog(LOG_WARNING, "%s dlt_user_init_state != INIT_DONE\n", __FUNCTION__); return DLT_RETURN_ERROR; } @@ -1578,8 +1599,8 @@ DltReturnValue dlt_unregister_app_flush_buffered_logs(void) if (g_dlt_is_child) return DLT_RETURN_ERROR; - if (!dlt_user_initialised) { - dlt_vlog(LOG_ERR, "%s dlt_user_initialised false\n", __func__); + if (!DLT_USER_INITALIZED) { + dlt_vlog(LOG_WARNING, "%s dlt_user_init_state != INIT_DONE\n", __FUNCTION__); return DLT_RETURN_ERROR; } @@ -1669,7 +1690,7 @@ DltReturnValue dlt_set_application_ll_ts_limit(DltLogLevelType loglevel, DltTrac return DLT_RETURN_WRONG_PARAMETER; } - if (!dlt_user_initialised) { + if (!DLT_USER_INITALIZED) { if (dlt_init() < 0) { dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__); return DLT_RETURN_ERROR; @@ -1719,7 +1740,7 @@ DltReturnValue dlt_set_log_mode(DltUserLogMode mode) return DLT_RETURN_WRONG_PARAMETER; } - if (!dlt_user_initialised) { + if (!DLT_USER_INITALIZED) { if (dlt_init() < 0) { dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__); return DLT_RETURN_ERROR; @@ -1735,7 +1756,7 @@ int dlt_set_resend_timeout_atexit(uint32_t timeout_in_milliseconds) if (g_dlt_is_child) return DLT_RETURN_ERROR; - if (dlt_user_initialised == 0) + if (DLT_USER_INITALIZED == 0) if (dlt_init() < 0) return -1; @@ -1813,27 +1834,34 @@ DltReturnValue dlt_user_log_write_start_internal(DltContext *handle, ret = dlt_user_log_write_start_init(handle, log, loglevel, is_verbose); if (ret == DLT_RETURN_TRUE) { /* initialize values */ - if (log->buffer == NULL) { + if ((NULL != log->buffer)) + { + free(log->buffer); + log->buffer = NULL; + } + else + { log->buffer = calloc(sizeof(unsigned char), dlt_user.log_buf_len); - - if (log->buffer == NULL) { - dlt_vlog(LOG_ERR, "Cannot allocate buffer for DLT Log message\n"); - return DLT_RETURN_ERROR; - } } - /* In non-verbose mode, insert message id */ - if (!is_verbose_mode(dlt_user.verbose_mode, log)) { - if ((sizeof(uint32_t)) > dlt_user.log_buf_len) { - return DLT_RETURN_USER_BUFFER_FULL; - } + if (log->buffer == NULL) { + dlt_vlog(LOG_ERR, "Cannot allocate buffer for DLT Log message\n"); + return DLT_RETURN_ERROR; + } + else + { + /* In non-verbose mode, insert message id */ + if (!is_verbose_mode(dlt_user.verbose_mode, log)) { + if ((sizeof(uint32_t)) > dlt_user.log_buf_len) + return DLT_RETURN_USER_BUFFER_FULL; - /* Write message id */ - memcpy(log->buffer, &(messageid), sizeof(uint32_t)); - log->size = sizeof(uint32_t); + /* Write message id */ + memcpy(log->buffer, &(messageid), sizeof(uint32_t)); + log->size = sizeof(uint32_t); - /* as the message id is part of each message in non-verbose mode, - * it doesn't increment the argument counter in extended header (if used) */ + /* as the message id is part of each message in non-verbose mode, + * it doesn't increment the argument counter in extended header (if used) */ + } } } @@ -1874,7 +1902,7 @@ DltReturnValue dlt_user_log_write_start_w_given_buffer(DltContext *handle, return ret; } - + DltReturnValue dlt_user_log_write_finish(DltContextData *log) { int ret = DLT_RETURN_ERROR; @@ -1913,8 +1941,8 @@ static DltReturnValue dlt_user_log_write_raw_internal(DltContextData *log, const return DLT_RETURN_WRONG_PARAMETER; } - if (!dlt_user_initialised) { - dlt_vlog(LOG_WARNING, "%s dlt_user_initialised false\n", __FUNCTION__); + if (!DLT_USER_INITALIZED) { + dlt_vlog(LOG_WARNING, "%s dlt_user_init_state != INIT_DONE\n", __FUNCTION__); return DLT_RETURN_ERROR; } @@ -2007,8 +2035,8 @@ static DltReturnValue dlt_user_log_write_generic_attr(DltContextData *log, const if (log == NULL) return DLT_RETURN_WRONG_PARAMETER; - if (!dlt_user_initialised) { - dlt_vlog(LOG_WARNING, "%s dlt_user_initialised false\n", __FUNCTION__); + if (!DLT_USER_INITALIZED) { + dlt_vlog(LOG_WARNING, "%s dlt_user_init_state != INIT_DONE\n", __FUNCTION__); return DLT_RETURN_ERROR; } @@ -2086,8 +2114,8 @@ static DltReturnValue dlt_user_log_write_generic_formatted(DltContextData *log, return DLT_RETURN_WRONG_PARAMETER; } - if (!dlt_user_initialised) { - dlt_vlog(LOG_WARNING, "%s dlt_user_initialised false\n", __FUNCTION__); + if (!DLT_USER_INITALIZED) { + dlt_vlog(LOG_WARNING, "%s dlt_user_init_state != INIT_DONE\n", __FUNCTION__); return DLT_RETURN_ERROR; } @@ -2162,8 +2190,8 @@ DltReturnValue dlt_user_log_write_uint(DltContextData *log, unsigned int data) if (log == NULL) return DLT_RETURN_WRONG_PARAMETER; - if (!dlt_user_initialised) { - dlt_vlog(LOG_WARNING, "%s dlt_user_initialised false\n", __FUNCTION__); + if (!DLT_USER_INITALIZED) { + dlt_vlog(LOG_WARNING, "%s dlt_user_init_state != INIT_DONE\n", __FUNCTION__); return DLT_RETURN_ERROR; } @@ -2227,7 +2255,7 @@ DltReturnValue dlt_user_log_write_uint_attr(DltContextData *log, unsigned int da if (log == NULL) return DLT_RETURN_WRONG_PARAMETER; - if (!dlt_user_initialised) { + if (!DLT_USER_INITALIZED) { dlt_vlog(LOG_WARNING, "%s dlt_user_initialised false\n", __FUNCTION__); return DLT_RETURN_ERROR; } @@ -2320,7 +2348,7 @@ DltReturnValue dlt_user_log_write_ptr(DltContextData *log, void *data) if (log == NULL) return DLT_RETURN_WRONG_PARAMETER; - if (!dlt_user_initialised) { + if (!DLT_USER_INITALIZED) { dlt_vlog(LOG_WARNING, "%s user_initialised false\n", __FUNCTION__); return DLT_RETURN_ERROR; } @@ -2348,8 +2376,8 @@ DltReturnValue dlt_user_log_write_int(DltContextData *log, int data) if (log == NULL) return DLT_RETURN_WRONG_PARAMETER; - if (!dlt_user_initialised) { - dlt_vlog(LOG_WARNING, "%s dlt_user_initialised false\n", __FUNCTION__); + if (!DLT_USER_INITALIZED) { + dlt_vlog(LOG_WARNING, "%s dlt_user_init_state != INIT_DONE\n", __FUNCTION__); return DLT_RETURN_ERROR; } @@ -2413,7 +2441,7 @@ DltReturnValue dlt_user_log_write_int_attr(DltContextData *log, int data, const if (log == NULL) return DLT_RETURN_WRONG_PARAMETER; - if (!dlt_user_initialised) { + if (!DLT_USER_INITALIZED) { dlt_vlog(LOG_WARNING, "%s dlt_user_initialised false\n", __FUNCTION__); return DLT_RETURN_ERROR; } @@ -2578,19 +2606,19 @@ DltReturnValue dlt_user_log_write_sized_constant_utf8_string_attr(DltContextData return is_verbose_mode(dlt_user.verbose_mode, log) ? dlt_user_log_write_sized_utf8_string_attr(log, text, length, name) : DLT_RETURN_OK; } -static DltReturnValue dlt_user_log_write_sized_string_utils_attr(DltContextData *log, const char *text, uint16_t length, const enum StringType type, const char *name, bool with_var_info) +static DltReturnValue dlt_user_log_write_sized_string_utils_attr(DltContextData *log, const char *text, size_t length, const enum StringType type, const char *name, bool with_var_info) { if ((log == NULL) || (text == NULL)) return DLT_RETURN_WRONG_PARAMETER; - if (!dlt_user_initialised) { - dlt_vlog(LOG_WARNING, "%s dlt_user_initialised false\n", __FUNCTION__); + if (!DLT_USER_INITALIZED) { + dlt_vlog(LOG_WARNING, "%s dlt_user_init_state != INIT_DONE\n", __FUNCTION__); return DLT_RETURN_ERROR; } const uint16_t name_size = (name != NULL) ? strlen(name)+1 : 0; - uint16_t arg_size = (uint16_t) (length + 1); + size_t arg_size = (size_t) (length + 1); size_t new_log_size = log->size + arg_size + sizeof(uint16_t); @@ -2615,13 +2643,13 @@ static DltReturnValue dlt_user_log_write_sized_string_utils_attr(DltContextData ret = DLT_RETURN_USER_BUFFER_FULL; /* Re-calculate arg_size */ - arg_size = (uint16_t) (dlt_user.log_buf_len - log->size - sizeof(uint16_t)); + arg_size = (size_t) (dlt_user.log_buf_len - log->size - sizeof(uint16_t)); size_t min_payload_str_truncate_msg = log->size + str_truncate_message_length + sizeof(uint16_t); if (is_verbose_mode(dlt_user.verbose_mode, log)) { min_payload_str_truncate_msg += sizeof(uint32_t); - arg_size -= (uint16_t) sizeof(uint32_t); + arg_size -= (size_t) sizeof(uint32_t); if (with_var_info) { min_payload_str_truncate_msg += sizeof(uint16_t) + name_size; arg_size -= sizeof(uint16_t) + name_size; @@ -2659,7 +2687,7 @@ static DltReturnValue dlt_user_log_write_sized_string_utils_attr(DltContextData } max_payload_str_msg -= reduce_size; - arg_size -= (uint16_t) reduce_size; + arg_size -= (size_t) reduce_size; } } @@ -2738,7 +2766,7 @@ static DltReturnValue dlt_user_log_write_string_utils_attr(DltContextData *log, if ((log == NULL) || (text == NULL)) return DLT_RETURN_WRONG_PARAMETER; - uint16_t length = (uint16_t) strlen(text); + size_t length = strlen(text); return dlt_user_log_write_sized_string_utils_attr(log, text, length, type, name, with_var_info); } @@ -3248,7 +3276,7 @@ DltReturnValue dlt_user_trace_network_segmented(DltContext *handle, return DLT_RETURN_ERROR; /* Send as normal trace if possible */ - if (header_len + payload_len + (uint16_t) sizeof(uint16_t) < dlt_user.log_buf_len) + if (header_len + payload_len + sizeof(uint16_t) < dlt_user.log_buf_len) return dlt_user_trace_network(handle, nw_trace_type, header_len, header, payload_len, payload); /* Allocate Memory */ @@ -3378,7 +3406,7 @@ DltReturnValue dlt_user_trace_network_truncated(DltContext *handle, header_len = 0; /* If truncation is allowed, check if we must do it */ - if ((allow_truncate > 0) && ((header_len + payload_len + (uint16_t) sizeof(uint16_t)) > dlt_user.log_buf_len)) { + if ((allow_truncate > 0) && ((header_len + payload_len + sizeof(uint16_t)) > dlt_user.log_buf_len)) { /* Identify as truncated */ if (dlt_user_log_write_string(&log, DLT_TRACE_NW_TRUNCATED) < DLT_RETURN_OK) { dlt_user_free_buffer(&(log.buffer)); @@ -3570,7 +3598,7 @@ DltReturnValue dlt_log_raw(DltContext *handle, DltLogLevelType loglevel, void *d DltReturnValue dlt_log_marker() { - if (!dlt_user_initialised) { + if (!DLT_USER_INITALIZED) { if (dlt_init() < DLT_RETURN_OK) { dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__); return DLT_RETURN_ERROR; @@ -3582,7 +3610,7 @@ DltReturnValue dlt_log_marker() DltReturnValue dlt_verbose_mode(void) { - if (!dlt_user_initialised) { + if (!DLT_USER_INITALIZED) { if (dlt_init() < DLT_RETURN_OK) { dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__); return DLT_RETURN_ERROR; @@ -3597,7 +3625,7 @@ DltReturnValue dlt_verbose_mode(void) DltReturnValue dlt_nonverbose_mode(void) { - if (!dlt_user_initialised) { + if (!DLT_USER_INITALIZED) { if (dlt_init() < DLT_RETURN_OK) { dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__); return DLT_RETURN_ERROR; @@ -3612,7 +3640,7 @@ DltReturnValue dlt_nonverbose_mode(void) DltReturnValue dlt_use_extended_header_for_non_verbose(int8_t use_extended_header_for_non_verbose) { - if (!dlt_user_initialised) { + if (!DLT_USER_INITALIZED) { if (dlt_init() < DLT_RETURN_OK) { dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__); return DLT_RETURN_ERROR; @@ -3627,7 +3655,7 @@ DltReturnValue dlt_use_extended_header_for_non_verbose(int8_t use_extended_heade DltReturnValue dlt_with_session_id(int8_t with_session_id) { - if (!dlt_user_initialised) { + if (!DLT_USER_INITALIZED) { if (dlt_init() < DLT_RETURN_OK) { dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__); return DLT_RETURN_ERROR; @@ -3642,7 +3670,7 @@ DltReturnValue dlt_with_session_id(int8_t with_session_id) DltReturnValue dlt_with_timestamp(int8_t with_timestamp) { - if (!dlt_user_initialised) { + if (!DLT_USER_INITALIZED) { if (dlt_init() < DLT_RETURN_OK) { dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__); return DLT_RETURN_ERROR; @@ -3657,7 +3685,7 @@ DltReturnValue dlt_with_timestamp(int8_t with_timestamp) DltReturnValue dlt_with_ecu_id(int8_t with_ecu_id) { - if (!dlt_user_initialised) { + if (!DLT_USER_INITALIZED) { if (dlt_init() < DLT_RETURN_OK) { dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__); return DLT_RETURN_ERROR; @@ -3672,7 +3700,7 @@ DltReturnValue dlt_with_ecu_id(int8_t with_ecu_id) DltReturnValue dlt_enable_local_print(void) { - if (!dlt_user_initialised) { + if (!DLT_USER_INITALIZED) { if (dlt_init() < DLT_RETURN_OK) { dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__); return DLT_RETURN_ERROR; @@ -3686,7 +3714,7 @@ DltReturnValue dlt_enable_local_print(void) DltReturnValue dlt_disable_local_print(void) { - if (!dlt_user_initialised) { + if (!DLT_USER_INITALIZED) { if (dlt_init() < DLT_RETURN_OK) { dlt_vlog(LOG_ERR, "%s Failed to initialise dlt", __FUNCTION__); return DLT_RETURN_ERROR; @@ -3712,10 +3740,12 @@ static void dlt_user_cleanup_handler(void *arg) DLT_SEM_FREE(); } -void dlt_user_housekeeperthread_function(__attribute__((unused)) void *ptr) +void dlt_user_housekeeperthread_function(void *ptr) { struct timespec ts; bool in_loop = true; + int signal_status = 0; + atomic_bool* dlt_housekeeper_running = (atomic_bool*)ptr; #ifdef __ANDROID_API__ sigset_t set; @@ -3743,6 +3773,13 @@ void dlt_user_housekeeperthread_function(__attribute__((unused)) void *ptr) pthread_cleanup_push(dlt_user_cleanup_handler, NULL); + // signal dlt thread to be running + *dlt_housekeeper_running = true; + signal_status = pthread_cond_signal(&dlt_housekeeper_running_cond); + if (signal_status != 0) { + dlt_log(LOG_CRIT, "Housekeeper thread failed to signal running state\n"); + } + while (in_loop) { /* Check for new messages from DLT daemon */ if (!dlt_user.disable_injection_msg) @@ -3787,7 +3824,7 @@ DltReturnValue dlt_user_log_init(DltContext *handle, DltContextData *log) if ((handle == NULL) || (log == NULL)) return DLT_RETURN_WRONG_PARAMETER; - if (!dlt_user_initialised) { + if (!DLT_USER_INITALIZED) { ret = dlt_init(); if (ret < DLT_RETURN_OK) { @@ -3811,8 +3848,8 @@ DltReturnValue dlt_user_log_send_log(DltContextData *log, int mtype) DltReturnValue ret = DLT_RETURN_OK; - if (!dlt_user_initialised) { - dlt_vlog(LOG_ERR, "%s dlt_user_initialised false\n", __FUNCTION__); + if (!DLT_USER_INITALIZED) { + dlt_vlog(LOG_WARNING, "%s dlt_user_init_state != INIT_DONE\n", __FUNCTION__); return DLT_RETURN_ERROR; } @@ -4920,15 +4957,63 @@ void dlt_user_test_corrupt_message_size(int enable, int16_t size) int dlt_start_threads() { - /* Start housekeeper thread */ + struct timespec time_to_wait; + struct timespec now; + int signal_status; + atomic_bool dlt_housekeeper_running = false; + + /* + * Configure the condition varibale to use CLOCK_MONOTONIC. + * This makes sure we're protected against changes in the system clock + */ + pthread_condattr_t attr; + pthread_condattr_init(&attr); + pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); + pthread_cond_init(&dlt_housekeeper_running_cond, &attr); + if (pthread_create(&(dlt_housekeeperthread_handle), 0, (void *)&dlt_user_housekeeperthread_function, - 0) != 0) { + &dlt_housekeeper_running) != 0) { dlt_log(LOG_CRIT, "Can't create housekeeper thread!\n"); return -1; } + clock_gettime(CLOCK_MONOTONIC, &now); + /* wait at most 10s */ + time_to_wait.tv_sec = now.tv_sec + 10; + time_to_wait.tv_nsec = 0; + + /* + * wait until the house keeper is up and running + * Even though the condition variable and the while are + * using the same time out the while loop is not a no op. + * This is due to the fact that the pthread_cond_timedwait + * can be woken before time is up and dlt_housekeeper_running is not true yet. + * (spurious wakeup) + * To protect against this, a while loop with a timeout is added + * */ + while (!dlt_housekeeper_running + && now.tv_sec <= time_to_wait.tv_sec) { + signal_status = pthread_cond_timedwait( + &dlt_housekeeper_running_cond, + &dlt_housekeeper_running_mutex, + &time_to_wait); + + /* otherwise it might be a spurious wakeup, try again until the time is over */ + if (signal_status == 0) { + break; + } + + clock_gettime(CLOCK_MONOTONIC, &now); + } + + if (signal_status != 0 && !dlt_housekeeper_running) { + dlt_log(LOG_CRIT, "Failed to wait for house keeper thread!\n"); + dlt_stop_threads(); + return -1; + } + #ifdef DLT_NETWORK_TRACE_ENABLE /* Start the segmented thread */ if (pthread_create(&(dlt_user.dlt_segmented_nwt_handle), NULL, @@ -5015,7 +5100,7 @@ void dlt_stop_threads() static void dlt_fork_child_fork_handler() { g_dlt_is_child = 1; - dlt_user_initialised = false; + dlt_user_init_state = INIT_UNITIALIZED; dlt_user.dlt_log_handle = -1; } |