diff options
author | Michele Calgaro <michele.calgaro@yahoo.it> | 2024-03-29 19:51:58 +0900 |
---|---|---|
committer | Michele Calgaro <michele.calgaro@yahoo.it> | 2024-04-04 10:22:18 +0900 |
commit | 57465e08e9cd1a17dffe841f2112859b41aba6e3 (patch) | |
tree | 4789cd2dcd2c35ba24d139bfb2bfe9b8f1110c1d | |
parent | b44105403d840b671b01410c34935de1c8738227 (diff) | |
download | tqt3-57465e08e9cd1a17dffe841f2112859b41aba6e3.tar.gz tqt3-57465e08e9cd1a17dffe841f2112859b41aba6e3.zip |
Prevent creation of text codecs when the application is shutting down. This resolves issue #142
Signed-off-by: Michele Calgaro <michele.calgaro@yahoo.it>
(cherry picked from commit 7563c4825f14a21f4d34c5187108b8ae71886dd1)
-rw-r--r-- | src/codecs/qtextcodec.cpp | 108 |
1 files changed, 74 insertions, 34 deletions
diff --git a/src/codecs/qtextcodec.cpp b/src/codecs/qtextcodec.cpp index 1c6df6953..69e56fd5b 100644 --- a/src/codecs/qtextcodec.cpp +++ b/src/codecs/qtextcodec.cpp @@ -89,7 +89,7 @@ #endif static TQValueList<TQTextCodec*> *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<TQTextCodec*> *ball = all; all = 0; TQValueList<TQTextCodec*>::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<TQTextCodec*>::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<TQTextCodec*>::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<TQTextCodec*>; (void)new TQLatin1Codec; |