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
This commit is contained in:
Daniel Gibson 2022-05-17 02:51:49 +02:00
parent 4b1369e859
commit ef1002e44f

View file

@ -33,7 +33,11 @@ If you have questions concerning this license or the applicable additional terms
#include "idlib/Str.h" #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 #define USE_STRING_DATA_ALLOCATOR
#endif #endif
@ -100,23 +104,30 @@ void idStr::ReAllocate( int amount, bool keepold ) {
#ifdef USE_STRING_DATA_ALLOCATOR #ifdef USE_STRING_DATA_ALLOCATOR
newbuffer = stringDataAllocator.Alloc( alloced ); newbuffer = stringDataAllocator.Alloc( alloced );
#else
newbuffer = new char[ alloced ];
#endif
if ( keepold && data ) { if ( keepold && data ) {
data[ len ] = '\0'; data[ len ] = '\0';
strcpy( newbuffer, data ); strcpy( newbuffer, data );
} }
if ( data && data != baseBuffer ) { if ( data && data != baseBuffer ) {
#ifdef USE_STRING_DATA_ALLOCATOR
stringDataAllocator.Free( data ); stringDataAllocator.Free( data );
#else
delete [] data;
#endif
} }
data = newbuffer; 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 #ifdef USE_STRING_DATA_ALLOCATOR
stringDataAllocator.Free( data ); stringDataAllocator.Free( data );
#else #else
delete[] data; free( data );
#endif #endif
data = baseBuffer; data = baseBuffer;
} }