0028217: Error handling is not thread safe and causing memory corruption and sporadic...
authorabv <abv@opencascade.com>
Thu, 29 Dec 2016 11:37:42 +0000 (14:37 +0300)
committerapn <apn@opencascade.com>
Thu, 29 Dec 2016 11:38:02 +0000 (14:38 +0300)
Static variable holding handle to the last raised exception is made thread-local on compilers that support C++11 keyword thread_local (MCVC++ 14+, GCC 4.8+, ICC 14+, CLang).
Test bugs fclasses bug28217 is added (BAD on vc < 14 and gcc < 4.8).

Test case tuning bugs/fclasses/bug28217

src/QABugs/QABugs_20.cxx
src/Standard/Standard_Failure.cxx
tests/bugs/fclasses/bug28217 [new file with mode: 0644]

index ffe937e..2b88cf8 100644 (file)
@@ -2140,6 +2140,48 @@ static Standard_Integer OCC27875(Draw_Interpretor& theDI,
   return 0;
 }
 
+#include <OSD_Parallel.hxx>
+
+namespace {
+  struct ExceptionRaiser
+  {
+    void operator () (int i) const
+    {
+      try 
+      {
+        f (i);
+      }
+      catch (Standard_ProgramError)
+      {
+        strlen (Standard_Failure::Caught()->GetMessageString());
+      }
+    }
+
+    void f(int i) const;
+  };
+
+  void ExceptionRaiser::f (int i) const
+  {
+    const char str[] = "0123456789";
+    Standard_ProgramError::Raise (str + i % 10);
+  }
+};
+
+static Standard_Integer OCC28217(Draw_Interpretor& theDI,
+                                 Standard_Integer /*theNArg*/,
+                                 const char ** /*theArgVal*/)
+{
+  NCollection_Array1<int> aVec (1, 10000);
+  for (int i=1; i < aVec.Length(); i++) 
+    aVec(i) = i;
+
+  ExceptionRaiser aProc;
+  OSD_Parallel::For (1, aVec.Length(), aProc);
+
+  theDI << "OCC28217: OK";
+  return 0;
+}
+
 
 void QABugs::Commands_20(Draw_Interpretor& theCommands) {
   const char *group = "QABugs";
@@ -2160,6 +2202,7 @@ void QABugs::Commands_20(Draw_Interpretor& theCommands) {
   theCommands.Add("OCC26270", "OCC26270 shape result", __FILE__, OCC26270, group);
   theCommands.Add ("OCC27552", "OCC27552", __FILE__, OCC27552, group); 
   theCommands.Add("OCC27875", "OCC27875 curve", __FILE__, OCC27875, group);
+  theCommands.Add("OCC28217", "OCC28217", __FILE__, OCC28217, group);
 
   return;
 }
index 07ecbcc..2e9c8a9 100644 (file)
@@ -58,12 +58,22 @@ static void deallocate_message(Standard_CString aMessage)
   }
 }
 
+// Define Standard_THREADLOCAL modifier as C++11 thread_local keyword
+// where it is available.
+#if (defined(__INTEL_COMPILER) && __INTEL_COMPILER > 1400) || \
+    (defined(__clang__)) /* assume standard CLang > 3.3 or XCode >= 8 */ || \
+    (defined(_MSC_VER) && _MSC_VER >= 1800) /* MSVC++ >= 14 */ || \
+    (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) /* GCC >= 4.8 */
+  #define Standard_THREADLOCAL thread_local
+#else
+  #define Standard_THREADLOCAL
+#endif
 
 // ******************************************************************
 //                           Standard_Failure                       *
 // ******************************************************************
 #ifndef NO_CXX_EXCEPTION
-static Handle(Standard_Failure) RaisedError;
+static Standard_THREADLOCAL Handle(Standard_Failure) RaisedError;
 #endif
 // ------------------------------------------------------------------
 //
diff --git a/tests/bugs/fclasses/bug28217 b/tests/bugs/fclasses/bug28217
new file mode 100644 (file)
index 0000000..8d5fe26
--- /dev/null
@@ -0,0 +1,17 @@
+puts "Testing intensive raising exceptions in parallel threads"
+puts "0028217: E r r o r handling is not thread safe and causing memory corruption and sporadic crashes"
+
+# this test will fail on vc10-13 and gcc less than 4.8
+set dver [dversion]
+if { ( [regexp {Compiler: MS Visual C[+][+] ([0-9]+)} $dver res ver] && $ver < 14 ) ||
+     ( [regexp {Compiler: GCC ([0-9]+[.][0-9]+)} $dver res ver] && $ver < 4.8 ) } {
+  puts "TODO OCC28217 ALL: TEST INCOMPLETE"
+  puts "TODO OCC28217 Windows: An exception was caught"
+  puts "TODO OCC28217 Windows: \\*\\* Exception \\*\\*.*"
+  puts "TODO ?OCC28217 Linux: An exception was caught"
+  puts "TODO ?OCC28217 Linux: \\*\\* Exception \\*\\*.*"
+  puts "TODO ?OCC28217 Linux: \\*\\*\\* Abort"
+  puts "TODO ?OCC28217 Linux: ... The exception is"
+}
+pload QAcommands
+OCC28217