static int dsetsignal (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
{
- // arm FPE handler if argument is provided and its first symbol is not '0'
- // or if environment variable CSF_FPE is set and its first symbol is not '0'
- bool setFPE = false;
- if (theArgNb > 1)
+ if (theArgNb < 2)
{
- setFPE = (theArgVec[1][0] == '1' || theArgVec[1][0] == 't');
+ theDI << "Catch signals: " << (OSD::ToCatchSignals() ? "1" : "0") << "\n"
+ << "Catch FPE: " << (OSD::ToCatchFloatingSignals() ? "1" : "0") << "\n";
+ return 0;
}
- else
+
+ Standard_Integer toSetSig = -1, toSetFpe = -1;
+ for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
+ {
+ TCollection_AsciiString anArg (theArgVec[anArgIter]);
+ anArg.LowerCase();
+ if (anArg == "-fpe"
+ && toSetFpe == -1
+ && anArgIter + 1 < theArgNb)
+ {
+ TCollection_AsciiString anArgNext (theArgVec[++anArgIter]);
+ if (anArgNext == "1")
+ {
+ toSetFpe = 1;
+ }
+ else if (anArgNext == "0")
+ {
+ toSetFpe = 0;
+ }
+ else
+ {
+ std::cout << "Syntax error at '" << anArg << "'\n";
+ return 1;
+ }
+ }
+ else if (toSetSig == -1
+ && (anArg == "0" || anArg == "1"))
+ {
+ toSetSig = anArg == "1" ? 1 : 0;
+ }
+ else
+ {
+ std::cout << "Syntax error at '" << anArg << "'\n";
+ return 1;
+ }
+ }
+ if (toSetSig == -1)
+ {
+ std::cout << "Syntax error: wrong number of arguments\n";
+ return 1;
+ }
+
+ if (toSetSig == 1
+ && toSetFpe == -1)
{
OSD_Environment aEnv ("CSF_FPE");
TCollection_AsciiString aEnvStr = aEnv.Value();
- setFPE = (! aEnvStr.IsEmpty() && aEnvStr.Value(1) != '0');
+ toSetFpe = (!aEnvStr.IsEmpty() && aEnvStr.Value(1) != '0') ? 1 : 0;
+ }
+
+ OSD::SetSignal (toSetSig == 1, toSetFpe == 1);
+ if (toSetSig == 1)
+ {
+ theDI << "Signal handlers are set, with FPE " << (toSetFpe == 1 ? "armed" : "disarmed");
+ }
+ else
+ {
+ theDI << "Signal handlers are reset to defaults, with FPE " << (toSetFpe == 1 ? "armed" : "disarmed");
}
- OSD::SetSignal (setFPE);
- theDI << "Signal handlers are set, with FPE " << (setFPE ? "armed" : "disarmed");
return 0;
}
__FILE__, dmeminfo, g);
theCommands.Add("dperf","dperf [reset] -- show performance counters, reset if argument is provided",
__FILE__,dperf,g);
- theCommands.Add("dsetsignal","dsetsignal [fpe=0] -- set OSD signal handler, with FPE option if argument is given",
+ theCommands.Add("dsetsignal","dsetsignal {0|1} [-fpe {0|1}] -- set OSD signal handler, with FPE option if argument is given",
__FILE__,dsetsignal,g);
theCommands.Add("dparallel",
#include <Standard_DivideByZero.hxx>
#include <Standard_Overflow.hxx>
+static Standard_Boolean OSD_WasSetSignal = Standard_False;
static Standard_THREADLOCAL Standard_Boolean fFltExceptions = Standard_False;
+//=======================================================================
+//function : ToCatchSignals
+//purpose :
+//=======================================================================
+Standard_Boolean OSD::ToCatchSignals()
+{
+ return OSD_WasSetSignal;
+}
+
//=======================================================================
//function : ToCatchFloatingSignals
//purpose :
lpXP->ExceptionRecord->ExceptionInformation[0]);
}
+//=======================================================================
+//function : SetFloatingSignals
+//purpose :
+//=======================================================================
+void OSD::SetFloatingSignals (Standard_Boolean theFloatingSignal)
+{
+ fFltExceptions = theFloatingSignal;
+ _controlfp (theFloatingSignal ? 0 : _OSD_FPX, _OSD_FPX);
+}
+
+//=======================================================================
+//function : SetThreadLocalSignal
+//purpose :
+//=======================================================================
+void OSD::SetThreadLocalSignal (Standard_Boolean theToCatch,
+ Standard_Boolean theFloatingSignal)
+{
+#ifdef _MSC_VER
+ _set_se_translator (theToCatch ? TranslateSE : NULL);
+#else
+ (void )theToCatch;
+#endif
+ SetFloatingSignals (theFloatingSignal);
+}
+
//=======================================================================
//function : SetSignal
//purpose :
//=======================================================================
-void OSD::SetSignal (const Standard_Boolean theFloatingSignal)
+void OSD::SetSignal (Standard_Boolean theToCatch,
+ Standard_Boolean theFloatingSignal)
{
Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
+ OSD_WasSetSignal = theToCatch;
#if !defined(OCCT_UWP) || defined(NTDDI_WIN10_TH2)
OSD_Environment env ("CSF_DEBUG_MODE");
TCollection_AsciiString val = env.Value();
// when user's code is compiled with /EHs
// Replaces the existing top-level exception filter for all existing and all future threads
// in the calling process
- ::SetUnhandledExceptionFilter (/*(LPTOP_LEVEL_EXCEPTION_FILTER)*/ WntHandler);
+ ::SetUnhandledExceptionFilter (theToCatch ? WntHandler : NULL);
#endif // NTDDI_WIN10_TH2
// Signal handlers will only be used when the method ::raise() will be used
// Handlers must be set for every thread
- if (signal (SIGSEGV, (void(*)(int))SIGWntHandler) == SIG_ERR)
+ void(*aHandler)(int) = theToCatch ? (void(*)(int))SIGWntHandler : (void(*)(int))SIG_DFL;
+ if (signal (SIGSEGV, aHandler) == SIG_ERR)
cout << "signal(OSD::SetSignal) error\n";
- if (signal (SIGFPE, (void(*)(int))SIGWntHandler) == SIG_ERR)
+ if (signal (SIGFPE, aHandler) == SIG_ERR)
cout << "signal(OSD::SetSignal) error\n";
- if (signal (SIGILL, (void(*)(int))SIGWntHandler) == SIG_ERR)
+ if (signal (SIGILL, aHandler) == SIG_ERR)
cout << "signal(OSD::SetSignal) error\n";
// Set Ctrl-C and Ctrl-Break handler
fCtrlBrk = Standard_False;
#ifndef OCCT_UWP
- SetConsoleCtrlHandler (&_osd_ctrl_break_handler, TRUE);
-#endif
-#ifdef _MSC_VER
-// _se_translator_function pOldSeFunc =
- _set_se_translator (TranslateSE);
-#endif
-
- fFltExceptions = theFloatingSignal;
- if (theFloatingSignal)
+ if (theToCatch)
{
- _controlfp (0, _OSD_FPX); // JR add :
+ SetConsoleCtrlHandler (&_osd_ctrl_break_handler, TRUE);
}
- else {
- _controlfp (_OSD_FPX, _OSD_FPX); // JR add :
+ else
+ {
+ SetConsoleCtrlHandler (NULL, FALSE);
}
-} // end OSD :: SetSignal
+#endif
+
+ SetThreadLocalSignal (theToCatch, theFloatingSignal);
+}
//============================================================================
//==== ControlBreak
#endif
+//=======================================================================
+//function : SetFloatingSignals
+//purpose :
+//=======================================================================
+void OSD::SetFloatingSignals (Standard_Boolean theFloatingSignal)
+{
+ fFltExceptions = theFloatingSignal;
+#if defined (__linux__)
+ if (theFloatingSignal)
+ {
+ feenableexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
+ }
+ else
+ {
+ fedisableexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
+ }
+#elif defined (sgi) || defined (IRIX)
+ char* aTrapFpeEnv = getenv ("TRAP_FPE");
+ if (aTrapFpeEnv == NULL)
+ {
+ #ifdef OCCT_DEBUG
+ std::cout << "On SGI you must set TRAP_FPE environment variable :\n"
+ "set env(TRAP_FPE) \"UNDERFL=FLUSH_ZERO;OVERFL=DEFAULT;DIVZERO=DEFAULT;INT_OVERFL=DEFAULT\" or\n"
+ "setenv TRAP_FPE \"UNDERFL=FLUSH_ZERO;OVERFL=DEFAULT;DIVZERO=DEFAULT;INT_OVERFL=DEFAULT\"\n";
+ #endif
+ }
+#endif
+}
+
+//=======================================================================
+//function : SetThreadLocalSignal
+//purpose :
+//=======================================================================
+void OSD::SetThreadLocalSignal (Standard_Boolean theToCatch,
+ Standard_Boolean theFloatingSignal)
+{
+ (void )theToCatch;
+ SetFloatingSignals (theFloatingSignal);
+}
+
//============================================================================
//==== SetSignal
//==== Set the differents signals:
//============================================================================
-void OSD::SetSignal(const Standard_Boolean aFloatingSignal)
+void OSD::SetSignal (Standard_Boolean theToCatch,
+ Standard_Boolean theFloatingSignal)
{
- struct sigaction act, oact;
- int stat = 0;
-
- if( aFloatingSignal ) {
- //==== Enable the floating point exceptions ===============
+ OSD_WasSetSignal = theToCatch;
+ SetFloatingSignals (theFloatingSignal);
#if defined (__sun) || defined (SOLARIS)
- sigfpe_handler_type PHandler = (sigfpe_handler_type) Handler ;
- stat = ieee_handler("set", "invalid", PHandler);
- stat = ieee_handler("set", "division", PHandler) || stat;
- stat = ieee_handler("set", "overflow", PHandler) || stat;
-
- //stat = ieee_handler("set", "underflow", PHandler) || stat;
- //stat = ieee_handler("set", "inexact", PHandler) || stat;
-
- if (stat) {
+ int aSunStat = 0;
+ sigfpe_handler_type anFpeHandler = (theToCatch && theFloatingSignal) ? (sigfpe_handler_type )Handler : NULL;
+ aSunStat = ieee_handler ("set", "invalid", anFpeHandler);
+ aSunStat = ieee_handler ("set", "division", anFpeHandler) || aSunStat;
+ aSunStat = ieee_handler ("set", "overflow", anFpeHandler) || aSunStat;
+ //aSunStat = ieee_handler ("set", "underflow", anFpeHandler) || aSunStat;
+ //aSunStat = ieee_handler ("set", "inexact", anFpeHandler) || aSunStat;
+ if (aSunStat)
+ {
#ifdef OCCT_DEBUG
- cerr << "ieee_handler does not work !!! KO " << endl;
-#endif
- }
-#elif defined (__linux__)
- feenableexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
- fFltExceptions = Standard_True;
+ std::cerr << "ieee_handler does not work !!! KO\n";
#endif
}
- else
- {
-#if defined (__linux__)
- fedisableexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
- fFltExceptions = Standard_False;
#endif
- }
-#if defined (sgi) || defined (IRIX )
- char *TRAP_FPE = getenv("TRAP_FPE") ;
- if ( TRAP_FPE == NULL ) {
-#ifdef OCCT_DEBUG
- cout << "On SGI you must set TRAP_FPE environment variable : " << endl ;
- cout << "set env(TRAP_FPE) \"UNDERFL=FLUSH_ZERO;OVERFL=DEFAULT;DIVZERO=DEFAULT;INT_OVERFL=DEFAULT\" or" << endl ;
- cout << "setenv TRAP_FPE \"UNDERFL=FLUSH_ZERO;OVERFL=DEFAULT;DIVZERO=DEFAULT;INT_OVERFL=DEFAULT\"" << endl ;
-#endif
- }
-#endif
+ struct sigaction act, oact;
//==== Save the old Signal Handler, and set the new one ===================
act.sa_flags = 0 ;
#endif
#ifdef SA_SIGINFO
- act.sa_flags = act.sa_flags | SA_SIGINFO ;
- act.sa_sigaction = /*(void(*)(int, siginfo_t *, void*))*/ Handler;
+ if (theToCatch)
+ {
+ act.sa_flags = act.sa_flags | SA_SIGINFO;
+ act.sa_sigaction = Handler;
+ }
+ else
+ {
+ act.sa_handler = SIG_DFL;
+ }
#else
- act.sa_handler = /*(SIG_PFV)*/ Handler;
+ act.sa_handler = theToCatch ? Handler : SIG_DFL;
#endif
//==== Always detected the signal "SIGFPE" =================================
- stat = sigaction(SIGFPE,&act,&oact); // ...... floating point exception
+ int stat = sigaction(SIGFPE,&act,&oact); // ...... floating point exception
if (stat) {
#ifdef OCCT_DEBUG
cerr << "sigaction does not work !!! KO " << endl;
# endif
#endif
-#ifdef SA_SIGINFO
- act.sa_sigaction = /*(void(*)(int, siginfo_t *, void*))*/ SegvHandler;
-#else
- act.sa_handler = /*(SIG_PFV)*/ SegvHandler;
-#endif
+ if (theToCatch)
+ {
+ #ifdef SA_SIGINFO
+ act.sa_sigaction = /*(void(*)(int, siginfo_t *, void*))*/ SegvHandler;
+ #else
+ act.sa_handler = /*(SIG_PFV)*/ SegvHandler;
+ #endif
+ }
if ( sigaction( SIGSEGV , &act , &oact ) ) // ...... segmentation violation
perror("OSD::SetSignal sigaction( SIGSEGV , &act , &oact ) ") ;
exit (1);
}
#endif
-
}
//============================================================================
#include <OSD_Exception_ACCESS_VIOLATION.hxx>
#include <OSD_Exception_STACK_OVERFLOW.hxx>
#include <OSD.hxx>
+#include <OSD_ThreadPool.hxx>
#include <STEPCAFControl_Writer.hxx>
#include <STEPControl_StepModelType.hxx>
#include <Interface_Static.hxx>
return 0;
}
+
+//! Auxiliary functor.
+struct TestParallelFunctor
+{
+ TestParallelFunctor() : myNbNotRaised (0), myNbSigSegv (0), myNbUnknown (0) {}
+
+ Standard_Integer NbNotRaised() const { return myNbNotRaised; }
+ Standard_Integer NbSigSegv() const { return myNbSigSegv; }
+ Standard_Integer NbUnknown() const { return myNbUnknown; }
+
+ void operator() (int theThreadId, int theTaskId) const
+ {
+ (void )theThreadId;
+ (void )theTaskId;
+
+ // Test Access Violation
+ {
+ try {
+ OCC_CATCH_SIGNALS
+ int* pint = NULL;
+ *pint = 4;
+ Standard_Atomic_Increment (&myNbNotRaised);
+ }
+ #ifdef _WIN32
+ catch (OSD_Exception_ACCESS_VIOLATION const&)
+ #else
+ catch (OSD_SIGSEGV const&)
+ #endif
+ {
+ Standard_Atomic_Increment (&myNbSigSegv);
+ }
+ catch (Standard_Failure const& )
+ {
+ Standard_Atomic_Increment (&myNbUnknown);
+ }
+ }
+ }
+private:
+ mutable volatile Standard_Integer myNbNotRaised;
+ mutable volatile Standard_Integer myNbSigSegv;
+ mutable volatile Standard_Integer myNbUnknown;
+};
+
+static Standard_Integer OCC30775 (Draw_Interpretor& theDI, Standard_Integer theNbArgs, const char** )
+{
+ if (theNbArgs != 1)
+ {
+ std::cout << "Syntax error: wrong number of arguments\n";
+ return 1;
+ }
+
+ Handle(OSD_ThreadPool) aPool = new OSD_ThreadPool (4);
+ OSD_ThreadPool::Launcher aLauncher (*aPool, 4);
+ TestParallelFunctor aFunctor;
+ aLauncher.Perform (0, 100, aFunctor);
+ theDI << "NbRaised: " << (aFunctor.NbSigSegv() + aFunctor.NbUnknown()) << "\n"
+ << "NbNotRaised: " << aFunctor.NbNotRaised() << "\n"
+ << "NbSigSeg: " << aFunctor.NbSigSegv() << "\n"
+ << "NbUnknown: " << aFunctor.NbUnknown() << "\n";
+ return 0;
+}
+
#if defined(_MSC_VER)
#pragma optimize( "", on )
#endif
theCommands.Add("OCC5739", "OCC5739 name shape step", __FILE__, OCC5739_UniAbs, group);
theCommands.Add("OCC6046", "OCC6046 nb_of_vectors size", __FILE__, OCC6046, group);
theCommands.Add("OCC5698", "OCC5698 wire", __FILE__, OCC5698, group);
- theCommands.Add("OCC6143", "OCC6143", __FILE__, OCC6143, group);
+ theCommands.Add("OCC6143", "OCC6143 catching signals", __FILE__, OCC6143, group);
+ theCommands.Add("OCC30775", "OCC30775 catching signals in threads", __FILE__, OCC30775, group);
theCommands.Add("OCC7141", "OCC7141 [nCount] aPath", __FILE__, OCC7141, group);
theCommands.Add("OCC7372", "OCC7372", __FILE__, OCC7372, group);
theCommands.Add("OCC8169", "OCC8169 edge1 edge2 plane", __FILE__, OCC8169, group);