From 97c7eef2a3ebc554c9954398f77e59818d63cb7e Mon Sep 17 00:00:00 2001 From: Jason Sopko Date: Sun, 6 Sep 2026 17:31:08 -0400 Subject: [PATCH] logger: Set the queue and the log file up before the writer thread starts datum_logger_init() returned as soon as the writer thread was created, while the thread was still allocating its queue and opening the log file. Anything logged in that window went to the console or nowhere, so the first lines of a run were missing from the file. Do that setup in init itself, before pthread_create, and leave the thread with only its loop; init passes it the open log handle as its argument. A failure to allocate or to open the file now returns -1 like the other init functions, and main exits on it, instead of panic_from_thread(), which from the main thread would only spin. Init now marks the logger ready only once the thread has started, so a failed pthread_create still logs to the console instead of queueing for a thread that does not exist. A run against an unreachable node now has its first startup lines in the file; on master the file starts several lines in. --- src/datum_gateway.c | 5 +++- src/datum_logger.c | 65 +++++++++++++++++++++++++-------------------- 2 files changed, 40 insertions(+), 30 deletions(-) diff --git a/src/datum_gateway.c b/src/datum_gateway.c index 88e786c5..4b84b580 100644 --- a/src/datum_gateway.c +++ b/src/datum_gateway.c @@ -196,7 +196,10 @@ int main(const int argc, const char * const * const argv) { datum_gateway_config_filename = arguments.config_file; // Initialize logger thread - datum_logger_init(); + if (datum_logger_init()) { + DLOG_FATAL("Error initializing the logger!"); + exit(1); + } if (datum_protocol_init()) { DLOG_FATAL("Error initializing the DATUM protocol!"); diff --git a/src/datum_logger.c b/src/datum_logger.c index 8f3af90e..f470087d 100644 --- a/src/datum_logger.c +++ b/src/datum_logger.c @@ -260,37 +260,10 @@ void * datum_logger_thread(void *ptr) { DLOG_MSG *msg; char time_buffer[20]; char log_line[1200]; - FILE *log_handle = NULL; + FILE *log_handle = ptr; // opened by datum_logger_init() time_t next_log_rotate = get_midnight_timestamp(); time_t log_file_opened = time(NULL); - msg_buffer[0] = calloc((DLOG_MSG_BUF_SIZE * 2) + (1024*8),1); - if (!msg_buffer[0]) { - DLOG(DLOG_LEVEL_FATAL, "Could not allocate memory for logger queue!"); - panic_from_thread(__LINE__); - } - // split the allocation in half for the double buffering - msg_buffer[1] = &msg_buffer[0][DLOG_MSG_BUF_SIZE + (1024*4)]; - - dlog_queue_max_entries = (DLOG_MSG_BUF_SIZE / sizeof(DLOG_MSG)) - 1; - if (dlog_queue_max_entries < 1024) dlog_queue_max_entries = 1024; - dlog_queue[0] = calloc(dlog_queue_max_entries * 2 * sizeof(DLOG_MSG),1); - if (!dlog_queue[0]) { - DLOG(DLOG_LEVEL_FATAL, "Could not allocate memory for logger queue list!"); - panic_from_thread(__LINE__); - } - dlog_queue[1] = &dlog_queue[0][dlog_queue_max_entries]; - - if ((log_to_file) && (log_file[0] != 0)) { - log_handle = fopen(log_file,"a"); - if (!log_handle) { - DLOG(DLOG_LEVEL_FATAL, "Could not open log file (%s): %s!", log_file, strerror(errno)); - panic_from_thread(__LINE__); - } - } - - // alert the masses. - datum_logger_initialized = true; DLOG(DLOG_LEVEL_DEBUG, "Logging thread started! (Approximately %d MB of RAM allocated for up to %d entries per cycle)", (DLOG_MSG_BUF_SIZE * 4)/1024/1024, dlog_queue_max_entries); lflush = 0; @@ -462,8 +435,42 @@ int datum_logger_init(void) { } pthread_t pthread_datum_logger_thread; + FILE *log_handle = NULL; - pthread_create(&pthread_datum_logger_thread, NULL, datum_logger_thread, NULL); + // Set the queue and the log file up here, before the writer thread + // exists, so a message logged right after init has somewhere to go. + msg_buffer[0] = calloc((DLOG_MSG_BUF_SIZE * 2) + (1024*8),1); + if (!msg_buffer[0]) { + DLOG(DLOG_LEVEL_FATAL, "Could not allocate memory for logger queue!"); + return -1; + } + // split the allocation in half for the double buffering + msg_buffer[1] = &msg_buffer[0][DLOG_MSG_BUF_SIZE + (1024*4)]; + + dlog_queue_max_entries = (DLOG_MSG_BUF_SIZE / sizeof(DLOG_MSG)) - 1; + if (dlog_queue_max_entries < 1024) dlog_queue_max_entries = 1024; + dlog_queue[0] = calloc(dlog_queue_max_entries * 2 * sizeof(DLOG_MSG),1); + if (!dlog_queue[0]) { + DLOG(DLOG_LEVEL_FATAL, "Could not allocate memory for logger queue list!"); + return -1; + } + dlog_queue[1] = &dlog_queue[0][dlog_queue_max_entries]; + + if ((log_to_file) && (log_file[0] != 0)) { + log_handle = fopen(log_file,"a"); + if (!log_handle) { + DLOG(DLOG_LEVEL_FATAL, "Could not open log file (%s): %s!", log_file, strerror(errno)); + return -1; + } + } + + const int result = pthread_create(&pthread_datum_logger_thread, NULL, datum_logger_thread, log_handle); + if (result != 0) { + DLOG_FATAL("datum_logger_init: pthread_create failed with code %d", result); + return -1; + } + + datum_logger_initialized = true; return 0; }