summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichele Calgaro <michele.calgaro@yahoo.it>2024-03-29 19:51:58 +0900
committerMichele Calgaro <michele.calgaro@yahoo.it>2024-04-04 10:22:18 +0900
commit57465e08e9cd1a17dffe841f2112859b41aba6e3 (patch)
tree4789cd2dcd2c35ba24d139bfb2bfe9b8f1110c1d
parentb44105403d840b671b01410c34935de1c8738227 (diff)
downloadtqt3-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.cpp108
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;