From 869d32a61adcbac146181ae8ef0163a1474a4f9d Mon Sep 17 00:00:00 2001 From: Marko Lindqvist Date: Sun, 25 Dec 2022 16:47:48 +0200 Subject: [PATCH 8/8] Replace localtime() calls with new thread safe fc_localtime() See osdn #46228 Signed-off-by: Marko Lindqvist --- client/gui-gtk-2.0/chatline.c | 6 ++-- client/gui-gtk-2.0/luaconsole.c | 6 ++-- client/gui-gtk-3.0/chatline.c | 6 ++-- client/gui-gtk-3.0/luaconsole.c | 6 ++-- client/gui-gtk-3.22/chatline.c | 6 ++-- client/gui-gtk-3.22/luaconsole.c | 6 ++-- common/fc_interface.c | 2 ++ configure.ac | 4 ++- server/console.c | 3 +- server/notify.c | 8 ++++-- utility/support.c | 48 ++++++++++++++++++++++++++++---- utility/support.h | 3 ++ 12 files changed, 76 insertions(+), 28 deletions(-) diff --git a/client/gui-gtk-2.0/chatline.c b/client/gui-gtk-2.0/chatline.c index e12396d8ba..628c3d7987 100644 --- a/client/gui-gtk-2.0/chatline.c +++ b/client/gui-gtk-2.0/chatline.c @@ -913,11 +913,11 @@ void real_output_window_append(const char *astring, if (gui_options.gui_gtk2_show_chat_message_time) { char timebuf[64]; time_t now; - struct tm *now_tm; + struct tm now_tm; now = time(NULL); - now_tm = localtime(&now); - strftime(timebuf, sizeof(timebuf), "[%H:%M:%S] ", now_tm); + fc_localtime(&now, &now_tm); + strftime(timebuf, sizeof(timebuf), "[%H:%M:%S] ", &now_tm); gtk_text_buffer_insert(buf, &iter, timebuf, -1); } diff --git a/client/gui-gtk-2.0/luaconsole.c b/client/gui-gtk-2.0/luaconsole.c index 1630c7e7d4..4202ac2dde 100644 --- a/client/gui-gtk-2.0/luaconsole.c +++ b/client/gui-gtk-2.0/luaconsole.c @@ -465,11 +465,11 @@ void real_luaconsole_append(const char *astring, if (gui_options.gui_gtk2_show_chat_message_time) { char timebuf[64]; time_t now; - struct tm *now_tm; + struct tm now_tm; now = time(NULL); - now_tm = localtime(&now); - strftime(timebuf, sizeof(timebuf), "[%H:%M:%S] ", now_tm); + fc_localtime(&now, &now_tm); + strftime(timebuf, sizeof(timebuf), "[%H:%M:%S] ", &now_tm); gtk_text_buffer_insert(buf, &iter, timebuf, -1); } diff --git a/client/gui-gtk-3.0/chatline.c b/client/gui-gtk-3.0/chatline.c index 79dd3f16cc..4a51dc6b8c 100644 --- a/client/gui-gtk-3.0/chatline.c +++ b/client/gui-gtk-3.0/chatline.c @@ -896,11 +896,11 @@ void real_output_window_append(const char *astring, if (gui_options.gui_gtk3_show_chat_message_time) { char timebuf[64]; time_t now; - struct tm *now_tm; + struct tm now_tm; now = time(NULL); - now_tm = localtime(&now); - strftime(timebuf, sizeof(timebuf), "[%H:%M:%S] ", now_tm); + fc_localtime(&now, &now_tm); + strftime(timebuf, sizeof(timebuf), "[%H:%M:%S] ", &now_tm); gtk_text_buffer_insert(buf, &iter, timebuf, -1); } diff --git a/client/gui-gtk-3.0/luaconsole.c b/client/gui-gtk-3.0/luaconsole.c index d59470cd5d..1a3ce9ffd4 100644 --- a/client/gui-gtk-3.0/luaconsole.c +++ b/client/gui-gtk-3.0/luaconsole.c @@ -474,11 +474,11 @@ void real_luaconsole_append(const char *astring, if (gui_options.gui_gtk3_show_chat_message_time) { char timebuf[64]; time_t now; - struct tm *now_tm; + struct tm now_tm; now = time(NULL); - now_tm = localtime(&now); - strftime(timebuf, sizeof(timebuf), "[%H:%M:%S] ", now_tm); + fc_localtime(&now, &now_tm); + strftime(timebuf, sizeof(timebuf), "[%H:%M:%S] ", &now_tm); gtk_text_buffer_insert(buf, &iter, timebuf, -1); } diff --git a/client/gui-gtk-3.22/chatline.c b/client/gui-gtk-3.22/chatline.c index 1c511a25ac..04ff128107 100644 --- a/client/gui-gtk-3.22/chatline.c +++ b/client/gui-gtk-3.22/chatline.c @@ -896,11 +896,11 @@ void real_output_window_append(const char *astring, if (GUI_GTK_OPTION(show_chat_message_time)) { char timebuf[64]; time_t now; - struct tm *now_tm; + struct tm now_tm; now = time(NULL); - now_tm = localtime(&now); - strftime(timebuf, sizeof(timebuf), "[%H:%M:%S] ", now_tm); + fc_localtime(&now, &now_tm); + strftime(timebuf, sizeof(timebuf), "[%H:%M:%S] ", &now_tm); gtk_text_buffer_insert(buf, &iter, timebuf, -1); } diff --git a/client/gui-gtk-3.22/luaconsole.c b/client/gui-gtk-3.22/luaconsole.c index a8d967aaab..d1be41d39e 100644 --- a/client/gui-gtk-3.22/luaconsole.c +++ b/client/gui-gtk-3.22/luaconsole.c @@ -475,11 +475,11 @@ void real_luaconsole_append(const char *astring, if (GUI_GTK_OPTION(show_chat_message_time)) { char timebuf[64]; time_t now; - struct tm *now_tm; + struct tm now_tm; now = time(NULL); - now_tm = localtime(&now); - strftime(timebuf, sizeof(timebuf), "[%H:%M:%S] ", now_tm); + fc_localtime(&now, &now_tm); + strftime(timebuf, sizeof(timebuf), "[%H:%M:%S] ", &now_tm); gtk_text_buffer_insert(buf, &iter, timebuf, -1); } diff --git a/common/fc_interface.c b/common/fc_interface.c index 06fadca60e..6dcb5eb214 100644 --- a/common/fc_interface.c +++ b/common/fc_interface.c @@ -53,6 +53,8 @@ struct functions *fc_interface_funcs(void) **************************************************************************/ void fc_interface_init(void) { + fc_support_init(); + fc_funcs = &fc_functions; /* Test the existence of each required function here! */ diff --git a/configure.ac b/configure.ac index 2d20a86fb6..afb880e3ef 100644 --- a/configure.ac +++ b/configure.ac @@ -1485,6 +1485,8 @@ feature_syslua=missing sys_lua=false])])]) fi +AC_CHECK_FUNCS([localtime_r]) + if test "x$sys_lua" != "xtrue" ; then dnl Checks needed for included lua. gl_FUNC_MKSTEMP @@ -1492,7 +1494,7 @@ if test "x$sys_lua" != "xtrue" ; then dnl if only "guessing yes", do not try to use mkstemp, but fallback AC_DEFINE([HAVE_MKSTEMP], [1], [Have working mkstemp]) fi - AC_CHECK_FUNCS([popen pclose _longjmp _setjmp gmtime_r localtime_r]) + AC_CHECK_FUNCS([popen pclose _longjmp _setjmp gmtime_r]) LUA_CFLAGS="-I\$(top_srcdir)/dependencies/lua-5.3/src" LUA_LIBS="\$(top_builddir)/dependencies/lua-5.3/src/liblua.la" diff --git a/server/console.c b/server/console.c index b679eeb9e7..b57c51f799 100644 --- a/server/console.c +++ b/server/console.c @@ -120,10 +120,11 @@ static const char *log_prefix(void) #ifdef LOG_TIMERS char timestr[32]; time_t timestamp; + struct tm tr; time(×tamp); strftime(timestr, sizeof(timestr), "%Y/%m/%d %H:%M:%S", - localtime(×tamp)); + fc_localtime(×tamp, &tr)); fc_snprintf(buf, sizeof(buf), "T%03d - %s", game.info.turn, timestr); diff --git a/server/notify.c b/server/notify.c index a0910a13b8..01ad881365 100644 --- a/server/notify.c +++ b/server/notify.c @@ -748,7 +748,7 @@ static bool event_cache_match(const struct event_cache_data *pdata, } /************************************************************************** - Send all available events. If include_public is TRUE, also fully global + Send all available events. If include_public is TRUE, also fully global message will be sent. **************************************************************************/ void send_pending_events(struct connection *pconn, bool include_public) @@ -762,9 +762,11 @@ void send_pending_events(struct connection *pconn, bool include_public) if (event_cache_match(pdata, pplayer, is_global_observer, include_public)) { if (game.server.event_cache.info) { - /* add turn and time to the message */ + struct tm tr; + + /* Add turn and time to the message */ strftime(timestr, sizeof(timestr), "%H:%M:%S", - localtime(&pdata->timestamp)); + fc_localtime(&pdata->timestamp, &tr)); pcm = pdata->packet; fc_snprintf(pcm.message, sizeof(pcm.message), "(T%d - %s) %s", pdata->packet.turn, timestr, pdata->packet.message); diff --git a/utility/support.c b/utility/support.c index 9745bdf9a2..3564ee8473 100644 --- a/utility/support.c +++ b/utility/support.c @@ -110,9 +110,13 @@ #ifndef HAVE_WORKING_VSNPRINTF static char *vsnprintf_buf = NULL; -fc_mutex vsnprintf_mutex; +static fc_mutex vsnprintf_mutex; #endif /* HAVE_WORKING_VSNPRINTF */ +#ifndef HAVE_LOCALTIME_R +static fc_mutex localtime_mutex; +#endif /* HAVE_LOCALTIME_R */ + /*************************************************************** Compare strings like strcmp(), but ignoring case. ***************************************************************/ @@ -810,19 +814,19 @@ int fc_vsnprintf(char *str, size_t n, const char *format, va_list ap) exit(EXIT_FAILURE); } + fc_allocate_mutex(&vsnprintf_mutex); + if (vsnprintf_buf == NULL) { - fc_init_mutex(&vsnprintf_mutex); vsnprintf_buf = malloc(VSNP_BUF_SIZE); if (vsnprintf_buf == NULL) { fprintf(stderr, "Could not allocate %i bytes for vsnprintf() " "replacement.", VSNP_BUF_SIZE); + fc_release_mutex(&vsnprintf_mutex); exit(EXIT_FAILURE); } } - fc_allocate_mutex(&vsnprintf_mutex); - vsnprintf_buf[VSNP_BUF_SIZE - 1] = '\0'; #ifdef HAVE_VSNPRINTF @@ -1193,6 +1197,22 @@ const char *fc_basename(const char *path) return basename(buf); } +/***************************************************************** + Thread safe localtime() replacement +*****************************************************************/ +struct tm *fc_localtime(const time_t *timep, struct tm *result) +{ +#ifdef HAVE_LOCALTIME_R + return localtime_r(timep, result); +#else /* HAVE_LOCALTIME_R */ + fc_allocate_mutex(&localtime_mutex); + memcpy(result, localtime(timep), sizeof(struct tm)); + fc_release_mutex(&localtime_mutex); + + return result; +#endif /* HAVE_LOCALTIME_R */ +} + /***************************************************************** Set quick_exit() callback if possible. *****************************************************************/ @@ -1205,6 +1225,20 @@ int fc_at_quick_exit(void (*func)(void)) #endif /* HAVE_AT_QUICK_EXIT */ } +/***************************************************************** + Initialize support module. +*****************************************************************/ +void fc_support_init(void) +{ +#ifndef HAVE_WORKING_VSNPRINTF + fc_init_mutex(&vsnprintf_mutex); +#endif /* HAVE_WORKING_VSNPRINTF */ + +#ifndef HAVE_LOCALTIME_R + fc_init_mutex(&localtime_mutex); +#endif /* HAVE_LOCALTIME_R */ +} + /***************************************************************** Free misc resources allocated by the support module. *****************************************************************/ @@ -1214,7 +1248,11 @@ void fc_support_free(void) if (vsnprintf_buf != NULL) { free(vsnprintf_buf); vsnprintf_buf = NULL; - fc_destroy_mutex(&vsnprintf_mutex); } + fc_destroy_mutex(&vsnprintf_mutex); #endif /* HAVE_WORKING_VSNPRINTF */ + +#ifndef HAVE_LOCALTIME_R + fc_destroy_mutex(&localtime_mutex); +#endif /* HAVE_LOCALTIME_R */ } diff --git a/utility/support.h b/utility/support.h index e71fb4af26..eb525b1fb2 100644 --- a/utility/support.h +++ b/utility/support.h @@ -124,6 +124,7 @@ int fc_strcasecmp(const char *str0, const char *str1); int fc_strncasecmp(const char *str0, const char *str1, size_t n); int fc_strncasequotecmp(const char *str0, const char *str1, size_t n); +void fc_support_init(void); void fc_support_free(void); size_t effectivestrlenquote(const char *str); @@ -191,6 +192,8 @@ char fc_tolower(char c); const char *fc_basename(const char *path); +struct tm *fc_localtime(const time_t *timep, struct tm *result); + void make_escapes(const char *str, char *buf, size_t buf_len); void remove_escapes(const char *str, bool full_escapes, char *buf, size_t buf_len); -- 2.35.1