From 79312dd52f991293e3dbf42e0e7ea602a41227e0 Mon Sep 17 00:00:00 2001 From: Marko Lindqvist Date: Sun, 23 Apr 2023 21:24:46 +0300 Subject: [PATCH 43/43] Make astr_vadd_at() thread safe See osdn #45906 Signed-off-by: Marko Lindqvist --- common/fc_interface.c | 5 ++++- utility/astring.c | 42 ++++++++++++++++++++++++++++++++++-------- utility/astring.h | 3 +++ 3 files changed, 41 insertions(+), 9 deletions(-) diff --git a/common/fc_interface.c b/common/fc_interface.c index bdeb122f79..af9747b262 100644 --- a/common/fc_interface.c +++ b/common/fc_interface.c @@ -16,6 +16,7 @@ #endif /* utility */ +#include "astring.h" #include "fciconv.h" #include "netfile.h" #include "shared.h" @@ -53,10 +54,11 @@ struct functions *fc_interface_funcs(void) /************************************************************************//** Initialize libfreeciv. - @param check_fc_interface Whether to lso test and initialize functions. + @param check_fc_interface Whether to also test and initialize functions. ****************************************************************************/ void libfreeciv_init(bool check_fc_interface) { + fc_astr_init(); fc_support_init(); init_nls(); @@ -93,4 +95,5 @@ void libfreeciv_free(void) free_nls(); fc_iconv_close(); fc_support_free(); + fc_astr_free(); } diff --git a/utility/astring.c b/utility/astring.c index 25f516d20e..9932c443fa 100644 --- a/utility/astring.c +++ b/utility/astring.c @@ -18,21 +18,21 @@ A common technique is to have some memory dynamically allocated (using malloc etc), to avoid compiled-in limits, but only allocate enough space as initially needed, and then realloc later if/when - require more space. Typically, the realloc is made a bit more than + require more space. Typically, the realloc is made a bit more than immediately necessary, to avoid frequent reallocs if the object - grows incrementally. Also, don't usually realloc at all if the - object shrinks. This is straightforward, but just requires a bit + grows incrementally. Also, don't usually realloc at all if the + object shrinks. This is straightforward, but just requires a bit of book-keeping to keep track of how much has been allocated etc. This module provides some tools to make this a bit easier. - This is deliberately simple and light-weight. The user is allowed + This is deliberately simple and light-weight. The user is allowed full access to the struct elements rather than use accessor functions etc. Note one potential hazard: when the size is increased (astr_reserve()), realloc (really fc_realloc) is used, which retains any data which was there previously, _but_: any external pointers into the allocated - memory may then become wild. So you cannot safely use such external + memory may then become wild. So you cannot safely use such external pointers into the astring data, except strictly between times when the astring size may be changed. @@ -66,6 +66,7 @@ /* utility */ #include "fcintl.h" +#include "fcthread.h" #include "log.h" /* fc_assert */ #include "mem.h" #include "support.h" /* fc_vsnprintf, fc_strlcat */ @@ -80,6 +81,8 @@ static const struct astring zero_astr = ASTRING_INIT; static char *astr_buffer = NULL; static size_t astr_buffer_alloc = 0; +static fc_mutex astr_mutex; + static inline char *astr_buffer_get(size_t *alloc); static inline char *astr_buffer_grow(size_t request, size_t *alloc); static void astr_buffer_free(void); @@ -123,6 +126,7 @@ static inline char *astr_buffer_grow(size_t request, size_t *alloc) astr_buffer = fc_realloc(astr_buffer, astr_buffer_alloc); *alloc = astr_buffer_alloc; + return astr_buffer; } @@ -144,7 +148,7 @@ void astr_init(struct astring *astr) /************************************************************************//** Free the memory associated with astr, and return astr to same - state as after astr_init. + state as after astr_init(). ****************************************************************************/ void astr_free(struct astring *astr) { @@ -163,14 +167,16 @@ void astr_free(struct astring *astr) char *astr_to_str(struct astring *astr) { char *str = astr->str; + *astr = zero_astr; + return str; } /************************************************************************//** Check that astr has enough size to hold n, and realloc to a bigger - size if necessary. Here n must be big enough to include the trailing - ascii-null if required. The requested n is stored in astr->n. + size if necessary. Here n must be big enough to include the trailing + ascii-null if required. The requested n is stored in astr->n. The actual amount allocated may be larger than n, and is stored in astr->n_alloc. ****************************************************************************/ @@ -218,6 +224,8 @@ static inline void astr_vadd_at(struct astring *astr, size_t at, size_t buffer_size; size_t req_len; + fc_mutex_allocate(&astr_mutex); + #ifdef HAVE_VA_COPY va_list copy; @@ -251,6 +259,8 @@ static inline void astr_vadd_at(struct astring *astr, size_t at, astr_reserve(astr, req_len); fc_strlcpy(astr->str + at, buffer, astr->n_alloc - at); + + fc_mutex_release(&astr_mutex); } /************************************************************************//** @@ -399,3 +409,19 @@ void astr_copy(struct astring *dest, const struct astring *src) astr_set(dest, "%s", src->str); } } + +/************************************************************************//** + Initialize astr API +****************************************************************************/ +void fc_astr_init(void) +{ + fc_mutex_init(&astr_mutex); +} + +/************************************************************************//** + Free astr handling API resources +****************************************************************************/ +void fc_astr_free(void) +{ + fc_mutex_destroy(&astr_mutex); +} diff --git a/utility/astring.h b/utility/astring.h index 8723308638..5efbaf3f12 100644 --- a/utility/astring.h +++ b/utility/astring.h @@ -83,6 +83,9 @@ const char *astr_build_and_list(struct astring *astr, void astr_copy(struct astring *dest, const struct astring *src) fc__attribute((nonnull (1, 2))); +void fc_astr_init(void); +void fc_astr_free(void); + /************************************************************************//** Returns the string. -- 2.39.2