diff --git a/src/codecs/qtextcodec.cpp b/src/codecs/qtextcodec.cpp index 1c6df695..69e56fd5 100644 --- a/src/codecs/qtextcodec.cpp +++ b/src/codecs/qtextcodec.cpp @@ -89,7 +89,7 @@ #endif static TQValueList *all = 0; -static bool destroying_is_ok; // starts out as 0 +static bool codecs_destroyed = false; static TQTextCodec * localeMapper = 0; class TQTextCodecCleanup { @@ -118,18 +118,16 @@ static TQTextCodecCleanup qtextcodec_cleanup; void TQTextCodec::deleteAllCodecs() { + codecs_destroyed = true; + if ( !all ) return; #ifdef TQT_THREAD_SUPPORT TQMutexLocker locker( tqt_global_mutexpool ? - tqt_global_mutexpool->get( &all ) : 0 ); - if ( !all ) - return; + tqt_global_mutexpool->get( &all ) : 0 ); #endif // TQT_THREAD_SUPPORT - destroying_is_ok = TRUE; - TQValueList *ball = all; all = 0; TQValueList::Iterator it; @@ -140,26 +138,10 @@ void TQTextCodec::deleteAllCodecs() ball->clear(); delete ball; - destroying_is_ok = FALSE; -} - - -static void realSetup(); - - -static inline void setup() -{ - if ( all ) return; - -#ifdef TQT_THREAD_SUPPORT - TQMutexLocker locker( tqt_global_mutexpool ? - tqt_global_mutexpool->get( &all ) : 0 ); - if ( all ) return; -#endif // TQT_THREAD_SUPPORT - - realSetup(); + localeMapper = 0; } +static void setup(); class TQTextStatelessEncoder: public TQTextEncoder { const TQTextCodec* codec; @@ -429,8 +411,16 @@ TQString TQTextStatelessDecoder::toUnicode(const char* chars, int len) */ TQTextCodec::TQTextCodec() { - setup(); - all->insert( all->begin(), this ); + // 'codecs_destroyed' should never be true at this point + if (!codecs_destroyed) + { + setup(); +#ifdef TQT_THREAD_SUPPORT + TQMutexLocker locker( tqt_global_mutexpool ? + tqt_global_mutexpool->get( &all ) : 0 ); +#endif // TQT_THREAD_SUPPORT + all->insert( all->begin(), this ); + } } @@ -442,8 +432,13 @@ TQTextCodec::TQTextCodec() */ TQTextCodec::~TQTextCodec() { - if ( !destroying_is_ok ) + if ( !codecs_destroyed ) tqWarning("TQTextCodec::~TQTextCodec() called by application"); + +#ifdef TQT_THREAD_SUPPORT + TQMutexLocker locker( tqt_global_mutexpool ? + tqt_global_mutexpool->get( &all ) : 0 ); +#endif // TQT_THREAD_SUPPORT if ( all ) all->remove( this ); } @@ -529,6 +524,11 @@ int TQTextCodec::simpleHeuristicNameMatch(const char* name, const char* hint) */ TQTextCodec* TQTextCodec::codecForIndex(int i) { + if (codecs_destroyed) + { + return nullptr; + } + setup(); return (uint)i >= all->count() ? 0 : *all->at(i); } @@ -540,6 +540,11 @@ TQTextCodec* TQTextCodec::codecForIndex(int i) */ TQTextCodec* TQTextCodec::codecForMib(int mib) { + if (codecs_destroyed) + { + return nullptr; + } + setup(); TQValueList::ConstIterator i; TQTextCodec* result=0; @@ -818,10 +823,15 @@ void TQTextCodec::setCodecForLocale(TQTextCodec *c) { TQTextCodec* TQTextCodec::codecForLocale() { - if ( localeMapper ) - return localeMapper; + if (codecs_destroyed) + { + return nullptr; + } - setup(); + if (!localeMapper) + { + setup(); + } return localeMapper; } @@ -838,6 +848,11 @@ TQTextCodec* TQTextCodec::codecForLocale() TQTextCodec* TQTextCodec::codecForName( const char* name, int accuracy ) { + if (codecs_destroyed) + { + return nullptr; + } + if ( !name || !*name ) return 0; @@ -879,6 +894,11 @@ TQTextCodec* TQTextCodec::codecForName( const char* name, int accuracy ) */ TQTextCodec* TQTextCodec::codecForContent(const char* chars, int len) { + if (codecs_destroyed) + { + return nullptr; + } + setup(); TQValueList::ConstIterator i; TQTextCodec* result = 0; @@ -2777,7 +2797,7 @@ static TQTextCodec *checkForCodec(const char *name) { return c; } -/* the next two functions are implicitely thread safe, +/* the next function is implicitely thread safe, as they are only called by setup() which uses a mutex. */ static void setupLocaleMapper() @@ -2901,12 +2921,32 @@ static void setupLocaleMapper() } -static void realSetup() +static void setup() { #if defined(QT_CHECK_STATE) - if ( destroying_is_ok ) - tqWarning( "TQTextCodec: creating new codec during codec cleanup!" ); + if ( codecs_destroyed ) + { + // If codecs have been destroyed, the application is being destroyed. + // Do not create new codecs since this could lead to SEGV while trying to + // print a message using tqWarning/tqDebug/tqFatal at this stage + // + // Note: the use of `printf` instead of `tqWarning` is intentional. We should never + // get to this line of code. If we do, we are in some strange exception that we + // didn't think of. Using `tqWarning` could potentially lead to an infinite loop with + // `tqWarning` trying to setup codecs and this method calling `tqWarning` again. + // Using `printf` makes sure this never happens, even for exceptions we didn't foresee. + printf("TQTextCodec: setup() called when codecs have already been destroyed\n"); fflush(stdout); + return; + } #endif + + if ( all ) return; + +#ifdef TQT_THREAD_SUPPORT + TQMutexLocker locker( tqt_global_mutexpool ? + tqt_global_mutexpool->get( &all ) : 0 ); +#endif // TQT_THREAD_SUPPORT + all = new TQValueList; (void)new TQLatin1Codec;