From ef1002e44f34be443a067c7064955fab51570533 Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Tue, 17 May 2022 02:51:49 +0200 Subject: [PATCH] Don't use stringDataAllocator in idStr, it's not thread-safe idStr is used in both the main thread and the async sound thread, so it should better be thread-safe.. idDynamicBlockAlloc is not. Use realloc() and free() instead. For some reason this caused a lot more crashes (due to inconsistencies in the allocator's heap) with newer Linux distros (like XUbuntu 20.04) and when using GCC9, while they rarely reproduced with GCC7 or on XUbuntu 18.04 fixes #391 --- idlib/Str.cpp | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/idlib/Str.cpp b/idlib/Str.cpp index 4ccfb96..9bd6b1b 100644 --- a/idlib/Str.cpp +++ b/idlib/Str.cpp @@ -33,7 +33,11 @@ If you have questions concerning this license or the applicable additional terms #include "idlib/Str.h" -#if !defined( ID_REDIRECT_NEWDELETE ) && !defined( MACOS_X ) +// DG: idDynamicBlockAlloc isn't thread-safe and idStr is used both in the main thread +// and the async thread! For some reason this seems to cause lots of problems on +// newer Linux distros if dhewm3 is built with GCC9 or newer (see #391). +// No idea why it apparently didn't cause that (noticeable) issues before.. +#if 0 // !defined( ID_REDIRECT_NEWDELETE ) && !defined( MACOS_X ) #define USE_STRING_DATA_ALLOCATOR #endif @@ -100,23 +104,30 @@ void idStr::ReAllocate( int amount, bool keepold ) { #ifdef USE_STRING_DATA_ALLOCATOR newbuffer = stringDataAllocator.Alloc( alloced ); -#else - newbuffer = new char[ alloced ]; -#endif if ( keepold && data ) { data[ len ] = '\0'; strcpy( newbuffer, data ); } if ( data && data != baseBuffer ) { -#ifdef USE_STRING_DATA_ALLOCATOR stringDataAllocator.Free( data ); -#else - delete [] data; -#endif } data = newbuffer; +#else + if ( data && data != baseBuffer ) { + data = (char *)realloc( data, newsize ); + } else { + newbuffer = (char *)malloc( newsize ); + if ( data && keepold ) { + memcpy( newbuffer, data, len ); + newbuffer[ len ] = '\0'; + } else { + newbuffer[ 0 ] = '\0'; + } + data = newbuffer; + } +#endif } /* @@ -129,7 +140,7 @@ void idStr::FreeData( void ) { #ifdef USE_STRING_DATA_ALLOCATOR stringDataAllocator.Free( data ); #else - delete[] data; + free( data ); #endif data = baseBuffer; }