pastebin - collaborative debugging tool
rovema.kpaste.net RSS


RDE: Fix hang in RDS code due to setlocale() abuse in multithreaded application
Posted by Anonymous on Fri 12th May 2023 12:23
raw | new post
modification of post by Anonymous (view diff)

  1. From 7ac9e7b777b25fe5ababedfc10b7adedbe56a04a Mon Sep 17 00:00:00 2001
  2. From: Roland Mainz <roland.mainz@nrubsig.org>
  3. Date: Fri, 12 May 2023 13:21:08 +0200
  4. Subject: [PATCH] Fix for #1836 ("Crash in ASAN durch Per-Thread abuse der
  5.  Locale").
  6.  
  7. Fix for #1836, by using POSIX per-thread locales, i.e.
  8. newlocale(), uselocale(), *_(), freelocale() etc.
  9. ---
  10. Base/CMakeLists.txt          |  6 ++++--
  11.  Base/PosixSystem.hpp         |  3 +++
  12.  Base/RovLocale.cpp           | 34 ++++++++++++++++++++++++++++++++++
  13.  Rdc/RdsTypes.cpp             | 28 +++++++++++++++++++++-------
  14.  Rdc/RdsUnit.h                | 12 ++++--------
  15.  Rds/RdsLib/RdsDataStream.cpp | 15 ++++++++++-----
  16.  Rds/RdsLib/RdsReal.cpp       | 19 ++++++++++++++-----
  17.  7 files changed, 90 insertions(+), 27 deletions(-)
  18.  create mode 100644 Base/RovLocale.cpp
  19.  
  20. diff --git a/Base/CMakeLists.txt b/Base/CMakeLists.txt
  21. index e5fd783..b3922e1 100644
  22. --- a/Base/CMakeLists.txt
  23. +++ b/Base/CMakeLists.txt
  24. @@ -34,13 +34,15 @@ else(WIN32)
  25.      if(RDE_BUILD)
  26.          set(PROJECT_SOURCE_FILES ${PROJECT_SOURCE_FILES}
  27.              RecursiveSemaphor.cpp
  28. -            PosixSystem.cpp )
  29. +            PosixSystem.cpp
  30. +           RovLocale.cpp )
  31.      else(RDE_BUILD)
  32.    set(PROJECT_SOURCE_FILES ${PROJECT_SOURCE_FILES}
  33.        TraceBack.cpp
  34.        RovFileSystem.cpp
  35.        RecursiveSemaphor.cpp
  36. -      PosixSystem.cpp )
  37. +      PosixSystem.cpp
  38. +      RovLocale.cpp )
  39.    endif(RDE_BUILD)
  40.  endif(WIN32)
  41.  
  42. diff --git a/Base/PosixSystem.hpp b/Base/PosixSystem.hpp
  43. index 9ec356a..cf7e2c7 100755
  44. --- a/Base/PosixSystem.hpp
  45. +++ b/Base/PosixSystem.hpp
  46. @@ -17,6 +17,7 @@
  47.  #endif
  48.  #include <time.h>
  49.  #include <pthread.h>
  50. +#include <locale.h>
  51.  #include <sys/socket.h>
  52.  #include <sys/types.h>
  53.  #include <sys/ipc.h>
  54. @@ -40,6 +41,8 @@
  55.  
  56.  #undef TEST_REALTIME
  57.  
  58. +extern locale_t rov_get_posix_localeobj(void);
  59. +
  60.  extern void dumpBackTrace( ostream & _outStr );
  61.  
  62.  //-DEFINES/MACROS--------------------------------------------------------------
  63. diff --git a/Base/RovLocale.cpp b/Base/RovLocale.cpp
  64. new file mode 100644
  65. index 0000000..afe7d2d
  66. --- /dev/null
  67. +++ b/Base/RovLocale.cpp
  68. @@ -0,0 +1,34 @@
  69. +///////////////////////////////////////////////////////////////////////////////
  70. +// RovLocale.cpp            POSIX i18n/l10n support functions
  71. +// Copyright                acontis technologies GmbH, Weingarten, Germany
  72. +// Response                 Roland Mainz <roland.mainz@rovema.de>
  73. +// Description              Support functions for i18n and l10n
  74. +///////////////////////////////////////////////////////////////////////////////
  75. +
  76. +#include "PosixSystem.hpp"
  77. +
  78. +/*
  79. + * ToDo:
  80. + * - Add implementations of |printf_l()|/|sprintf_l()| etc.
  81. + */
  82. +
  83. +static pthread_once_t  posix_localeobj_init = PTHREAD_ONCE_INIT;
  84. +static locale_t                posix_localeobj = 0;
  85. +
  86. +static void init_posix_localeobj(void)
  87. +{
  88. +       /*
  89. +        * FIXME: We should have a function to free this locale
  90. +        * object, but currently RDS does not release any
  91. +        * resources at shutdown, and only writes data to NVRAM
  92. +        * before |exit()|.
  93. +        */
  94. +       posix_localeobj = newlocale(LC_ALL_MASK, "POSIX", (locale_t)0);
  95. +}
  96. +
  97. +locale_t rov_get_posix_localeobj(void)
  98. +{
  99. +       (void)pthread_once(&posix_localeobj_init, init_posix_localeobj);
  100. +      
  101. +       return posix_localeobj;
  102. +}
  103. diff --git a/Rdc/RdsTypes.cpp b/Rdc/RdsTypes.cpp
  104. index 213cabd..68c92b8 100755
  105. --- a/Rdc/RdsTypes.cpp
  106. +++ b/Rdc/RdsTypes.cpp
  107. @@ -619,8 +619,15 @@ RINLINE T_Bool g_ReadNumericalValueFromString (
  108.                                                )
  109.  {
  110.  #ifdef JNA
  111. -  std::locale actualLocal; //automatically initialized
  112. -  std::setlocale(LC_NUMERIC, "en_US.utf8");
  113. +  locale_t saved_locale;
  114. +  locale_t posix_locale;
  115. +
  116. +  /*
  117. +   * Use POSIX locale because the code below uses functions which
  118. +   * parse floating-poing values using locale-specific functions
  119. +   */
  120. +  posix_locale = rov_get_posix_localeobj();
  121. +  saved_locale = uselocale(posix_locale);
  122.  #endif
  123.    T_Bool bOk = true;
  124.    const string sToken = C_RovTool::strParse (_rsString, RDF_SEPARATOR);
  125. @@ -717,8 +724,8 @@ RINLINE T_Bool g_ReadNumericalValueFromString (
  126.               _eValueType);
  127.  
  128.    } // end if (!bOk)
  129. - #ifdef JNA
  130. -  locale::global(actualLocal);
  131. +#ifdef JNA
  132. +  (void)uselocale(saved_locale);
  133.  #endif
  134.    return(bOk);
  135.  }    // end of readNumericalValueFromString
  136. @@ -764,8 +771,15 @@ RINLINE T_Bool writeNumericalValueToString (
  137.                                             )
  138.  {
  139.  #ifdef JNA
  140. -  std::locale actualLocal; //automatically initialized
  141. -  std::setlocale(LC_NUMERIC, "en_US.utf8");
  142. +  locale_t saved_locale;
  143. +  locale_t posix_locale;
  144. +
  145. +  /*
  146. +   * Use POSIX locale because the code below uses functions which
  147. +   * parse floating-poing values using locale-specific functions
  148. +   */
  149. +  posix_locale = rov_get_posix_localeobj();
  150. +  saved_locale = uselocale(posix_locale);
  151.  #endif
  152.    register T_Bool bOk = true;
  153.    if ( _pValue != NULL )
  154. @@ -827,7 +841,7 @@ RINLINE T_Bool writeNumericalValueToString (
  155.    }   // end if (_pValue != NULL)
  156.    _rsString += RDF_SEPARATOR;
  157.  #ifdef JNA
  158. -  locale::global(actualLocal);
  159. +  (void)uselocale(saved_locale);
  160.  #endif
  161.    return(bOk);
  162.  }    // end of writeNumericalValueToString
  163. diff --git a/Rdc/RdsUnit.h b/Rdc/RdsUnit.h
  164. index 11c8e38..ed39e22 100755
  165. --- a/Rdc/RdsUnit.h
  166. +++ b/Rdc/RdsUnit.h
  167. @@ -559,15 +559,11 @@ public:
  168.  //******************************************************************************
  169.  RINLINE T_Bool  C_RdsUnitSize::convertString2Double(const string &_anyStr, T_Double64 & _anyDouble)
  170.  {
  171. - #ifdef JNA
  172. -    std::locale actualLocal; //automatically initialized
  173. -    std::setlocale(LC_NUMERIC, "en_US.utf8");
  174. -#endif
  175. +    locale_t posix_locale = rov_get_posix_localeobj();
  176. +
  177.      T_String stopStr = (T_String) _anyStr.c_str();
  178. -    _anyDouble = strtod(stopStr, & stopStr);
  179. -#ifdef JNA
  180. -    locale::global(actualLocal);
  181. -#endif
  182. +    _anyDouble = strtod_l(stopStr, & stopStr, posix_locale);
  183. +
  184.      return true;
  185.  }    // end C_RdsUnitSize::convertString2Double
  186.  
  187. diff --git a/Rds/RdsLib/RdsDataStream.cpp b/Rds/RdsLib/RdsDataStream.cpp
  188. index fedff82..b91d504 100755
  189. --- a/Rds/RdsLib/RdsDataStream.cpp
  190. +++ b/Rds/RdsLib/RdsDataStream.cpp
  191. @@ -847,10 +847,15 @@ RINLINE T_Bool C_RdsDataStream::readStream(C_RdsLoadFlags &_roLoadFlags,
  192.          const T_Bool _bAutoNvRamInit /* = false */,
  193.          const T_Name _SRamFileName /* = NULL */) {
  194.      T_Bool bOk = true;
  195. +    locale_t saved_locale;
  196. +    locale_t posix_locale;
  197.  
  198. -    // Set LC_NUMERIC to C because the real values are written as 123.456
  199. -    std::string oldLocale(setlocale(LC_NUMERIC, nullptr));
  200. -    setlocale(LC_NUMERIC, "C");
  201. +    /*
  202. +     * Use POSIX locale because the code below uses functions which
  203. +     * parse floating-poing values using locale-specific functions
  204. +     */
  205. +    posix_locale = rov_get_posix_localeobj();
  206. +    saved_locale = uselocale(posix_locale);
  207.  
  208.      if (0 == _pRdsAbsDirectory)
  209.          _pRdsAbsDirectory = this;
  210. @@ -975,7 +980,7 @@ RINLINE T_Bool C_RdsDataStream::readStream(C_RdsLoadFlags &_roLoadFlags,
  211.                                          m_poRdsLocalClientID, _fileName,
  212.                                          onlyOnRdf.c_str(),
  213.                                          m_sActFileName.c_str());
  214. -                                setlocale(LC_NUMERIC, oldLocale.c_str());
  215. +                                (void)uselocale(saved_locale);
  216.                                  bOk = false;
  217.                                  return (bOk);
  218.                              }
  219. @@ -1024,7 +1029,7 @@ RINLINE T_Bool C_RdsDataStream::readStream(C_RdsLoadFlags &_roLoadFlags,
  220.              poRdsError->m_iLine);
  221.      assert(checkTree(_pRdsAbsDirectory));
  222.  // delete[] szBuffer;
  223. -    setlocale(LC_NUMERIC, oldLocale.c_str());
  224. +    (void)uselocale(saved_locale);
  225.      return (bOk);
  226.  } // end of C_RdsDataStream::readStream
  227.  
  228. diff --git a/Rds/RdsLib/RdsReal.cpp b/Rds/RdsLib/RdsReal.cpp
  229. index c8f28b2..8f5e72e 100755
  230. --- a/Rds/RdsLib/RdsReal.cpp
  231. +++ b/Rds/RdsLib/RdsReal.cpp
  232. @@ -44,6 +44,8 @@
  233.  #include "RdsClientLocal.h"
  234.  #include "DExtMath.hpp"
  235.  
  236. +#include <locale.h>
  237. +
  238.  
  239.  #define RINLINE
  240.  
  241. @@ -1539,10 +1541,15 @@ RINLINE T_Bool C_RdsUnit::readUnitSizeFile(const string &_path)
  242.  {
  243.    T_Bool isOK = true;
  244.  
  245. -  char savedLocale[32];
  246. -  /* Get the name of the current locale.  */
  247. -  strncpy(savedLocale, setlocale (LC_NUMERIC, NULL), 32);
  248. -  setlocale(LC_NUMERIC, "C");
  249. +  locale_t saved_locale;
  250. +  locale_t posix_locale;
  251. +
  252. +  /*
  253. +   * Use POSIX locale because the code below uses functions which
  254. +   * parse floating-poing values using locale-specific functions
  255. +   */
  256. +  posix_locale = rov_get_posix_localeobj();
  257. +  saved_locale = uselocale(posix_locale);
  258.  
  259.    string completeFileName(SIZE_AND_UNIT_DIR);
  260.    if ( !_path.empty() )
  261. @@ -1617,7 +1624,9 @@ RINLINE T_Bool C_RdsUnit::readUnitSizeFile(const string &_path)
  262.      poSuRdsError->perrorLog (errorMsg.str().c_str());
  263.      isOK = false;
  264.    } // end else !inStream
  265. -  setlocale(LC_NUMERIC, savedLocale);
  266. +  
  267. +  (void)uselocale(saved_locale);
  268. +
  269.    return(isOK);
  270.  } // end of method C_RdsUnit::readUnitSizeFile
  271.  
  272. --
  273. 2.30.2

Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:

To highlight particular lines, prefix each line with {%HIGHLIGHT}




All content is user-submitted.
The administrators of this site (kpaste.net) are not responsible for their content.
Abuse reports should be emailed to us at