0022545: Improved exception handling
authorRoman Lygin <roman.lygin@gmail.com>
Thu, 15 Nov 2012 09:17:30 +0000 (13:17 +0400)
committerRoman Lygin <roman.lygin@gmail.com>
Thu, 15 Nov 2012 09:17:30 +0000 (13:17 +0400)
src/OSD/OSD.cdl
src/OSD/OSD_signal_WNT.cxx

index 85f08da..7235c41 100755 (executable)
@@ -28,17 +28,17 @@ package OSD
  --   2.0
  --   3.0
  --   Windows NT 30/09/96 ( EUG )
- ---Purpose: Set of Operating Sytem Dependent Tools 
+ ---Purpose: Set of Operating Sytem Dependent Tools
  --         (O)perating (S)ystem (D)ependent
 
-uses  
+uses
 
-    Standard ,  
-    Quantity ,  
+    Standard ,
+    Quantity ,
     TCollection
 
 is
+
  exception OSDError inherits Failure from Standard  ;
 
  imported Function;
@@ -51,7 +51,7 @@ is
    ---Purpose: This is set of possible machine types
    --          used in OSD_Host::MachineType
 
- enumeration SysType is Unknown,Default,UnixBSD, UnixSystemV, VMS, OS2, 
+ enumeration SysType is Unknown,Default,UnixBSD, UnixSystemV, VMS, OS2,
                         OSF, MacOs, Taligent, WindowsNT, LinuxREDHAT,Aix;
    ---Purpose: Thisd is a set of possible system types.
    --          'Default' means SysType of machine operating this process.
@@ -59,7 +59,7 @@ is
    --          All UNIX-like are grouped under "UnixBSD" or "UnixSystemV".
    --          Such systems are Solaris, NexTOS ...
    --          A category of systems accept MSDOS-like path such as
-   --          WindowsNT and OS2. 
+   --          WindowsNT and OS2.
 
  enumeration FromWhere is FromBeginning, FromHere, FromEnd;
    ---Purpose: Used by OSD_File in the method Seek.
@@ -70,7 +70,7 @@ is
    --
    --          ReadLock allows only one reading of the file at a time.
    --
-   --          WriteLock prevents others writing into a file(excepted the user 
+   --          WriteLock prevents others writing into a file(excepted the user
    --          who puts the lock)but allows everybody to read.
    --
    --          ExclusiveLock prevents reading and writing except for the
@@ -94,8 +94,8 @@ is
  enumeration KindFile is FILE, DIRECTORY, LINK, SOCKET, UNKNOWN;
    ---Purpose: Specifies the type of files.
 
- private enumeration WhoAmI is  WDirectory, WDirectoryIterator, 
-             WEnvironment, WFile, WFileNode, WFileIterator, WMailBox, 
+ private enumeration WhoAmI is  WDirectory, WDirectoryIterator,
+             WEnvironment, WFile, WFileNode, WFileIterator, WMailBox,
              WPath, WProcess, WProtection, WSemaphore, WHost, WDisk,
              WChronometer, WSharedMemory, WTimer, WPackage, WPrinter,
              WEnvironmentIterator;
@@ -109,7 +109,7 @@ is
          class Protection;
              ---Purpose: Gets and sets protection attributes of 'system , user ,
              --          group, and world'.
-  
+
          class Path;
              ---Purpose: Manages independent system path translation.
 
@@ -132,7 +132,7 @@ is
              ---Purpose: Searches sub-directories in current directory.
 
          class Chronometer;
-             ---Purpose: Measures time elapsed for performance program tests. 
+             ---Purpose: Measures time elapsed for performance program tests.
              --          Measures CPU time consumed by a method call.
 
          class Timer;
@@ -155,17 +155,17 @@ is
              ---Purpose: Process specific oriented tools
 
          class SharedMemory;
-             ---Purpose: Manages shared memory. 
+             ---Purpose: Manages shared memory.
 
          class Semaphore;
              ---Purpose: Manages semaphores.
+
 --         class Mutex is alias Mutex from Standard;
              ---Purpose: Mutex object to synchronize threads within one process
+
          class MailBox;
              ---Purpose: Manages asynchronous mail boxes.
-    
+
          class SharedLibrary;
              ---Purpose: Provides tools to load a shared library
              --          and retrieve the address of an entry point.
@@ -177,11 +177,11 @@ is
              ---Purpose: A tool to manage threads
 
     class Real2String;
-             ---Purpose: Convertion of CString to Real and reciprocally   
+             ---Purpose: Convertion of CString to Real and reciprocally
 
     class Localizer;
              ---Purpose: Manages locale.
-   
+
 
     -----------------------------------------------
     --  UNIX specific exceptions and enumeration --
@@ -196,12 +196,12 @@ is
     exception SIGBUS  inherits Signal;
     exception SIGSEGV inherits Signal;
     exception SIGSYS  inherits Signal;
-    
+
 
     enumeration Signals is
       ---purpose:
       --     The "posix" signals.
-      --     
+      --
       S_SIGHUP,          -- "hangup."
       S_SIGINT,          -- "interrupt."
       S_SIGQUIT,         -- "quit."
@@ -218,13 +218,13 @@ is
       S_FPE_FLTUND_TRAP, -- "floating underflow."
       S_FPE_FLTINEX_TRAP -- "floating inexact result."
     end Signals;
-    
+
     ----------------------------------------
     -- Exceptions ( Windows NT specific ) --
     ----------------------------------------
 
     exception Exception inherits Failure   from  Standard;
-    
+
     exception Exception_ACCESS_VIOLATION         inherits Exception;
     exception Exception_ARRAY_BOUNDS_EXCEEDED    inherits Exception;
     exception Exception_FLT_DENORMAL_OPERAND     inherits Exception;
@@ -249,35 +249,35 @@ is
     -- Handler and SegvHandler (UNIX specific ) --
     ----------------------------------------------
 
-    -- 
-    --     Handler(aSignal: Signals; aCode: Signals) 
-    --     
-    Handler(aSignal: Signals; aSigInfo: Address; aContext: Address)    
+    --
+    --     Handler(aSignal: Signals; aCode: Signals)
+    --
+
+    Handler(aSignal: Signals; aSigInfo: Address; aContext: Address)
     ---Purpose:
     --   1) Raise a exception when aSignal is a floating point signal.
     --    aSignal is SIGFPE.
-    --    aCode is 
+    --    aCode is
     --        (FPE:  Floating Point Exception)
     --        (FLT:  FLoaTing operation.)
     --        (INT:  INTeger  operation.)
     --        (DIV:  DIVided by zero.)
     --        (OVF:  OVerFlow.)
     --        (INEX: INEXact operation.)
-    --        
+    --
     --        FPE_FLTDIV_TRAP  (the exception "DivideByZero" is raised.)
     --        FPE_INTDIV_TRAP  (the exception "DivideByZero" is raised.)
-    --        
+    --
     --        FPE_FLTOVF_TRAP  (the exception "Overflow" is raised.)
     --        FPE_INTOVF_TRAP  (the exception "Overflow" is raised.)
-    --        
+    --
     --        FPE_FLTINEX_TRAP (the exception "NumericError" is raised.)
-    --        
+    --
     --   2) Display the signal name, and call "exit" with signal number for
     --   a "Hardware" signal.
-    --   
+    --
     raises
-        DivideByZero, 
+        DivideByZero,
     Overflow,
     Underflow,
         SIGHUP,
@@ -338,42 +338,77 @@ is
         --  2) Displays a message box 'Continue' - 'Debugger' - 'Stop' if the environment
         --     variable 'CSF_EXCEPTION_PROMPT' is set and takes appropriate action.
         --     Raises an exception otherwise.
-    SetSignal(aFloatingSignal: Boolean = Standard_True);
+
+    SetSignal(theFloatingSignal: Boolean = Standard_True);
     ---Purpose:
-    --   1) Arms some floating point signals, and sets a "Handler" for them.
-    --   2) Sets a "Handler" for the "Hardware" signals.
-    --   For Win32 users: under VC++ you can control which method of handling
-    --   exceptions is used by means of UseSETranslator method before calling
-    --   SetSignal
+    -- Sets signal and exception handlers.
+    -- <b>Windows-specific notes<\b>
+    -- Compiled with MS VC++ sets 3 main handlers:
+    -- @li Signal handlers (via ::signal() functions) that translate system signals
+    --     (SIGSEGV, SIGFPE, SIGILL) into C++ exceptions (classes inheriting
+    --     Standard_Failure). They only be called if user calls ::raise() function
+    --     with one of supported signal type set.
+    -- @li Exception handler OSD::WntHandler() (via ::SetUnhandledExceptionFilter())
+    --     that will be used when user's code is compiled with /EHs option.
+    -- @li Structured exception (SE) translator (via _set_se_translator()) that
+    --     translates SE exceptions (aka asynchronous exceptions) into the
+    --     C++ exceptions inheriting Standard_Failure. This translator will be
+    --     used when user's code is compiled with /EHa option.
+    -- .
+    -- This approach ensures that regardless of the option the user chooses to
+    -- compile his code with (/EHs or /EHa), signals (or SE exceptions) will be
+    -- translated into Open CASCADE C++ exceptions.
+    -- .
+    -- If @a theFloatingSignal is TRUE then floating point exceptions will be
+    -- generated in accordance with the mask
+    -- <tt>_EM_INVALID | _EM_DENORMAL | _EM_ZERODIVIDE | _EM_OVERFLOW<\tt> that is
+    -- used to call ::_controlfp() system function. If @a theFloatingSignal is FALSE
+    -- corresponding operations (e.g. division by zero) will gracefully complete
+    -- without an exception.
+    -- .
+    -- <b>Unix-specific notes<\b>
+    -- OSD::SetSignal() sets handlers (via ::sigaction()) for multiple signals
+    -- (SIGFPE, SIGSEGV, etc). Currently the number of handled signals is much
+    -- greater than for Windows, in the future this may change to provide better
+    -- consistency with Windows.
+    -- .
+    -- @a theFloatingSignal is recognized on Sun Solaris, Linux, and SGI Irix to
+    -- generate floating-point exception according to the mask
+    -- <tt>FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW</tt> (in Linux conventions).<br>
+    -- When compiled with OBJS macro defined, already set signal handlers (e.g.
+    -- by Data Base Managers) are not redefined.
+    -- .
+    -- <b>Common notes<\b>
+    -- If OSD::SetSignal() method is used in at least one thread, it must also be
+    -- called in any other thread where Open CASCADE will be used, to ensure
+    -- consistency of behavior. Its @a aFloatingSignal argument must be consistent
+    -- across threads.
+    -- .
+    -- Keep in mind that whether the C++ exception will really be thrown (i.e.
+    -- ::throw() will be called) is regulated by the NO_CXX_EXCEPTIONS and
+    -- OCC_CONVERT_SIGNALS macros used during compilation of Open CASCADE and
+    -- user's code. Refer to Foundation Classes User's Guide for further details.
     --
-    --  Warning:
-    --   Some "Data Base Managers" use their own "Handler" for the signals 
-    --   such as  "SIGSEGV". So if a "Handler" is set for a signal it will
-    --   not be replaced by Standard "Handler". It is managed by OBJS
-    --   preprocessor definition.
-    --
-    ---Level: Internal    
 
     AvailableMemory returns Integer from Standard;
     ---Purpose: Returns available memory in Kilobytes.
     ---Level: Advanced
-     
+
     SecSleep(aDelay: Integer from Standard);
     ---Purpose: Commands the process to sleep for a number of seconds.
-    ---Level: Public    
+    ---Level: Public
 
     MilliSecSleep(aDelay: Integer from Standard);
     ---Purpose: Commands the process to sleep for a number of milliseconds
-    ---Level: Public    
+    ---Level: Public
 
-    RealToCString(aReal: Real; aString:out PCharacter)  
+    RealToCString(aReal: Real; aString:out PCharacter)
         returns Boolean ;
     ---Purpose:
     --  Converts aReal into aCstring in exponential format with a period as
     --  decimal point, no thousand separator and no grouping of digits.
     --  The conversion is independant from the current locale
-    ---Level: Public    
+    ---Level: Public
 
     CStringToReal(aString: CString; aReal: out Real) returns Boolean ;
     ---Purpose:
@@ -381,46 +416,31 @@ is
     --  decimal point, no thousand separator and no grouping of digits
     --  into aReal .
     --  The conversion is independant from the current locale.
-    ---Level: Public    
+    ---Level: Public
 
     IsDivisible(aDividend, aDivisor: Real from Standard)
     returns Boolean from Standard;
     ---Purpose: Tests if the quotient theDividend/theDivisor
     --          does not overflow
-    ---Level: Public    
-    
+    ---Level: Public
+
     GetExponent(aReal: Real from Standard)
     returns Integer from Standard;
     ---Purpose: Returns the exponent in base 2 of a floating-point number.
-    ---Level: Public    
-    
+    ---Level: Public
+
     GetMantissa(aReal: Real from Standard)
     returns Real from Standard;
     ---Purpose: Returns the mantissa of a floating-point number.
-    ---Level: Public    
-    
+    ---Level: Public
+
     -------------------------
     -- Windows NT specific --
     -------------------------
-                            
+
     ControlBreak raises  Exception_CTRL_BREAK;
     ---Purpose: since Windows NT does not support 'SIGINT' signal like UNIX,
     --          then this method checks whether Ctrl-Break keystroke was or
     --          not. If yes then raises Exception_CTRL_BREAK.
 
-    UseSETranslator(useSE : Boolean);
-    ---Purpose: Defines whether SetSignal must use _se_translator_function or
-    --          SetUnhandledExceptionFilter and signal to catch system
-    --          exceptions. The default behaviour is to use SE translator.
-    --  Warning: Using SE translator method SetSignal should be called for each
-    --          new created thread, while using the alternative method 
-    --          the exception handler is established once for the whole
-    --          process and all its threads.
-    --          This function takes effect only under VC++ compiler.
-
-    UseSETranslator returns Boolean;
-    ---Purpose: Returns the current value of the flag set by above method.
-
 end OSD;
-
-
index 396aad4..f49c663 100755 (executable)
 
 #include <OSD.ixx>
 
-static Standard_Boolean fSETranslator =
-#ifdef _MSC_VER
-                           Standard_True;
-#else
-                           Standard_False;
-#endif
-
 #ifdef WNT
 
 //---------------------------- Windows NT System --------------------------------
@@ -53,6 +46,7 @@ static Standard_Boolean fSETranslator =
 #include <Standard_DivideByZero.hxx>
 #include <Standard_Overflow.hxx>
 #include <Standard_ProgramError.hxx>
+#include <Standard_Mutex.hxx>
 
 #include <OSD_WNT_1.hxx>
 
@@ -70,14 +64,16 @@ static Standard_Boolean fFltExceptions;
 static Standard_Boolean fDbgLoaded;
 static Standard_Boolean fCtrlBrk;
 
+// used to forbid simultaneous execution of setting / executing handlers
+static Standard_Mutex THE_SIGNAL_MUTEX;
+
 static LONG __fastcall _osd_raise ( DWORD, LPTSTR );
 static BOOL WINAPI     _osd_ctrl_break_handler ( DWORD );
 
 extern "C" Standard_EXPORT LONG _osd_debug   ( void );
-extern "C" Standard_EXPORT void _debug_break ( Standard_PCharacter );
 
 MB_DESC fatalErrorDesc[] = {
-                                                                         
+
                  { MBT_ICON,   ( int )IDI_HAND              },
                  { MBT_BUTTON, IDYES,    TEXT( "Continue" ) },
                  { MBT_BUTTON, IDNO,     TEXT( "Debugger" ) },
@@ -85,104 +81,21 @@ MB_DESC fatalErrorDesc[] = {
 
 };
 
-static LONG CallHandler (DWORD, ptrdiff_t, ptrdiff_t);
-static void SIGWntHandler (int, int);
-
-
 //# define _OSD_FPX ( _EM_INVALID | _EM_DENORMAL | _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW )
 # define _OSD_FPX ( _EM_INVALID | _EM_DENORMAL | _EM_ZERODIVIDE | _EM_OVERFLOW )
 
-//============================================================================
-//==== WntHandler
-//============================================================================
-
-Standard_Integer OSD :: WntHandler ( const Standard_Address exceptionInfo )
-{
-
- LPEXCEPTION_POINTERS lpXP = ( LPEXCEPTION_POINTERS )exceptionInfo;
- DWORD                dwExceptionCode = lpXP -> ExceptionRecord -> ExceptionCode;
-
-// cout << "WntHandler " << dwExceptionCode << " " << lpXP->ExceptionRecord->ExceptionInformation[1]
-//      << " " <<lpXP->ExceptionRecord->ExceptionInformation[0] << endl ;
-
- return CallHandler( dwExceptionCode ,
-                     lpXP -> ExceptionRecord -> ExceptionInformation[ 1 ] ,
-                     lpXP -> ExceptionRecord -> ExceptionInformation[ 0 ] ) ;
-
-}
-
-//============================================================================
-//==== SIGWntHandler
-//============================================================================
-
-static void SIGWntHandler(int signum , int sub_code ) {
-
-#if !defined(__CYGWIN32__) && !defined(__MINGW32__)
-
-//        cout << "SIGWntHandler " << signum << " subcode " << sub_code << endl ;
-       switch( signum ) {
-       case SIGFPE :
-         if ( signal( signum , ( void (*)(int) ) &SIGWntHandler ) == SIG_ERR )
-            cout << "signal error" << endl ;
-          switch( sub_code ) {
-          case _FPE_INVALID :
-            CallHandler( EXCEPTION_FLT_INVALID_OPERATION ,0,0) ;
-            break ;
-          case _FPE_DENORMAL :
-            CallHandler( EXCEPTION_FLT_DENORMAL_OPERAND ,0,0) ;
-            break ;
-          case _FPE_ZERODIVIDE :
-            CallHandler( EXCEPTION_FLT_DIVIDE_BY_ZERO ,0,0) ;
-            break ;
-          case _FPE_OVERFLOW :
-            CallHandler( EXCEPTION_FLT_OVERFLOW ,0,0) ;
-            break ;
-          case _FPE_UNDERFLOW :
-            CallHandler( EXCEPTION_FLT_UNDERFLOW ,0,0) ;
-            break ;
-          case _FPE_INEXACT :
-            CallHandler( EXCEPTION_FLT_INEXACT_RESULT ,0,0) ;
-            break ;
-          default:
-            cout << "SIGWntHandler(default) -> Standard_NumericError::Raise(\"Floating Point Error\");"
-                 << endl ;
-            Standard_NumericError::Raise("Floating Point Error");
-            break ;
-          }
-          break ;
-       case SIGSEGV :
-         if ( signal( signum , ( void (*)(int) )  &SIGWntHandler ) == SIG_ERR )
-            cout << "signal error" << endl ;
-          CallHandler( EXCEPTION_ACCESS_VIOLATION ,0,0) ;
-         break ;
-       case SIGILL :
-         if ( signal( signum , ( void (*)(int) )  &SIGWntHandler ) == SIG_ERR )
-            cout << "signal error" << endl ;
-          CallHandler( EXCEPTION_ILLEGAL_INSTRUCTION ,0,0) ;
-         break ;
-        default:
-          cout << "SIGWntHandler unexpected signal : "
-               << signum << endl ;
-          break ;
-       }
-// cout << "return from SIGWntHandler -> DebugBreak " << endl ;
- DebugBreak ();
-
-#endif
-
-}
-
-//============================================================================
-//==== CallHandler 
-//============================================================================
-
-static LONG CallHandler (DWORD dwExceptionCode ,
-                        ptrdiff_t ExceptionInformation1 ,
-                        ptrdiff_t ExceptionInformation0)
+//=======================================================================
+//function : CallHandler
+//purpose  :
+//=======================================================================
+static LONG CallHandler (DWORD dwExceptionCode,
+                         ptrdiff_t ExceptionInformation1,
+                         ptrdiff_t ExceptionInformation0)
 {
 
 #if !defined(__CYGWIN32__) && !defined(__MINGW32__)
 
+ Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
  static TCHAR         buffer[ 2048 ];
  int                  flterr = 0;
 
@@ -318,6 +231,10 @@ static LONG CallHandler (DWORD dwExceptionCode ,
 
 
  if ( idx && fMsgBox && dwExceptionCode != EXCEPTION_NONCONTINUABLE_EXCEPTION ) {
+     // reset FP operations before message box, otherwise it may fail to show up
+    _fpreset();
+    _clearfp();
+
   MessageBeep ( MB_ICONHAND );
   int msgID = MsgBox ( NULL, buffer, TEXT( "Error detected" ), 4, fatalErrorDesc );
 //  cout << "flterr" << flterr << " fFltExceptions " << fFltExceptions << endl ;
@@ -360,23 +277,104 @@ static LONG CallHandler (DWORD dwExceptionCode ,
 //     cout << "OSD::WntHandler _controlfp( 0, _OSD_FPX ) " << hex << _controlfp(0,0) << dec << endl ;
    }
  }
-
  return _osd_raise ( dwExceptionCode, buffer );
-
 #else
  return 0;
 #endif
+}
+
+//=======================================================================
+//function : SIGWntHandler
+//purpose  : Will only be used if user calls ::raise() function with
+//           signal type set in OSD::SetSignal() - SIGSEGV, SIGFPE, SIGILL
+//           (the latter will likely be removed in the future)
+//=======================================================================
+static void SIGWntHandler (int signum, int sub_code)
+{
+#if !defined(__CYGWIN32__) && !defined(__MINGW32__)
+    Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
+    switch( signum ) {
+    case SIGFPE :
+      if ( signal( signum , ( void (*)(int) ) &SIGWntHandler ) == SIG_ERR )
+            cout << "signal error" << endl ;
+          switch( sub_code ) {
+          case _FPE_INVALID :
+            CallHandler( EXCEPTION_FLT_INVALID_OPERATION ,0,0) ;
+            break ;
+          case _FPE_DENORMAL :
+            CallHandler( EXCEPTION_FLT_DENORMAL_OPERAND ,0,0) ;
+            break ;
+          case _FPE_ZERODIVIDE :
+            CallHandler( EXCEPTION_FLT_DIVIDE_BY_ZERO ,0,0) ;
+            break ;
+          case _FPE_OVERFLOW :
+            CallHandler( EXCEPTION_FLT_OVERFLOW ,0,0) ;
+            break ;
+          case _FPE_UNDERFLOW :
+            CallHandler( EXCEPTION_FLT_UNDERFLOW ,0,0) ;
+            break ;
+          case _FPE_INEXACT :
+            CallHandler( EXCEPTION_FLT_INEXACT_RESULT ,0,0) ;
+            break ;
+          default:
+            cout << "SIGWntHandler(default) -> Standard_NumericError::Raise(\"Floating Point Error\");"
+                 << endl ;
+            Standard_NumericError::Raise("Floating Point Error");
+            break ;
+          }
+          break ;
+       case SIGSEGV :
+      if ( signal( signum , ( void (*)(int) )  &SIGWntHandler ) == SIG_ERR )
+            cout << "signal error" << endl ;
+          CallHandler( EXCEPTION_ACCESS_VIOLATION ,0,0) ;
+         break ;
+    case SIGILL :
+      if ( signal( signum , ( void (*)(int) )  &SIGWntHandler ) == SIG_ERR )
+            cout << "signal error" << endl ;
+          CallHandler( EXCEPTION_ILLEGAL_INSTRUCTION ,0,0) ;
+         break ;
+        default:
+          cout << "SIGWntHandler unexpected signal : "
+               << signum << endl ;
+          break ;
+       }
+ DebugBreak ();
+#endif
+}
+
+//=======================================================================
+//function : WntHandler
+//purpose  : Will be used when user's code is compiled with /EHs
+//           option and unless user sets his own exception handler with 
+//           ::SetUnhandledExceptionFilter().
+//=======================================================================
+Standard_Integer OSD::WntHandler (const Standard_Address theExceptionInfo)
+{
+  LPEXCEPTION_POINTERS lpXP = (LPEXCEPTION_POINTERS )theExceptionInfo;
+  DWORD                dwExceptionCode = lpXP->ExceptionRecord->ExceptionCode;
 
-}  // end OSD :: WntHandler
+  return CallHandler (dwExceptionCode,
+                      lpXP->ExceptionRecord->ExceptionInformation[1],
+                      lpXP->ExceptionRecord->ExceptionInformation[0]);
+}
 
 //=======================================================================
 //function : TranslateSE
 //purpose  : Translate Structural Exceptions into C++ exceptions
+//           Will be used when user's code is compiled with /EHa option
 //=======================================================================
-
 #ifdef _MSC_VER
+
+// If this file compiled with the default MSVC options for exception
+// handling (/GX or /EHsc) then the following warning is issued:
+//   warning C4535: calling _set_se_translator() requires /EHa
+// However it is correctly inserted and used when user's code compiled with /EHa.
+// So, here we disable the warning.
+#pragma warning (disable:4535)
+
 static void TranslateSE( unsigned int theCode, EXCEPTION_POINTERS* theExcPtr )
 {
+  Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
   ptrdiff_t info1 = 0, info0 = 0;
   if ( theExcPtr ) {
     info1 = theExcPtr->ExceptionRecord->ExceptionInformation[1];
@@ -386,87 +384,60 @@ static void TranslateSE( unsigned int theCode, EXCEPTION_POINTERS* theExcPtr )
 }
 #endif
 
-//============================================================================
-//==== SetSignal 
-//============================================================================
-
-#ifdef _MSC_VER
-// MSV 31.08.2005
-// If we compile this file under MSVC 7.1 with the default options for 
-// exception handling (/GX or /EHsc) then the following warning is issued:
-//   warning C4535: calling _set_se_translator() requires /EHa
-// Till now all worked with the default options, and there was no difference
-// found in exception handling behaviour between /EHa and /EHs options. 
-// So, here we disable the warning, and leave the default compiler options.
-// If some reason appears to turn to /EHa option this pragma can be removed.
-#pragma warning (disable:4535)
-#endif
-
-void OSD :: SetSignal ( const Standard_Boolean aFloatingSignal ) {
-
+//=======================================================================
+//function : SetSignal
+//purpose  :
+//=======================================================================
+void OSD::SetSignal (const Standard_Boolean theFloatingSignal)
+{
 #if !defined(__CYGWIN32__) && !defined(__MINGW32__)
+  Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
+  LPTOP_LEVEL_EXCEPTION_FILTER aPreviousFilter;
+
+  OSD_Environment env (TEXT("CSF_DEBUG_MODE"));
+  TCollection_AsciiString val = env.Value();
+  if (!env.Failed())
+  {
+    cout << "Environment variable CSF_DEBUG_MODE setted.\n";
+    fMsgBox = Standard_True;
+  }
+  else
+  {
+    fMsgBox = Standard_False;
+  }
 
- static int first_time = 1 ;
- LPTOP_LEVEL_EXCEPTION_FILTER aPreviousFilter ;
-
- if ( first_time ) {
-//   OSD_Environment         env (  TEXT( "CSF_EXCEPTION_PROMPT" )  );
-   OSD_Environment         env (  TEXT( "CSF_DEBUG_MODE" )  );
-   TCollection_AsciiString val;
-
-   val = env.Value ();
-
-   if (  !env.Failed ()  ) {
-     cout << "Environment variable CSF_DEBUG_MODE setted." << endl ;
-     fMsgBox = Standard_True;
-   }
-   else {
-//     cout << "Environment variable CSF_DEBUG_MODE not setted." << endl ;
-     fMsgBox = Standard_False;
-   }
-
-   if (!fSETranslator) {
-     aPreviousFilter =
-       SetUnhandledExceptionFilter ((LPTOP_LEVEL_EXCEPTION_FILTER)&OSD::WntHandler);
-//   cout << "SetUnhandledExceptionFilter previous filer : " << hex << aPreviousFilter << dec << endl ;
-
-     if ( signal( SIGSEGV , ( void (*)(int) ) &SIGWntHandler ) == SIG_ERR )
-       cout << "signal(OSD::SetSignal) error" << endl ;
-     if ( signal( SIGFPE , ( void (*)(int) ) &SIGWntHandler ) == SIG_ERR )
-       cout << "signal(OSD::SetSignal) error" << endl ;
-     if ( signal( SIGILL , ( void (*)(int) ) &SIGWntHandler ) == SIG_ERR )
-       cout << "signal(OSD::SetSignal) error" << endl ;
-   }
-
-   fCtrlBrk = Standard_False;
-   SetConsoleCtrlHandler ( &_osd_ctrl_break_handler, TRUE );
- }
+  // Set exception handler (ignored when running under debugger). It will be used in most cases
+  // 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
+  aPreviousFilter = ::SetUnhandledExceptionFilter ((LPTOP_LEVEL_EXCEPTION_FILTER )&OSD::WntHandler);
+
+  // 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)
+    cout << "signal(OSD::SetSignal) error\n";
+  if (signal (SIGFPE,  (void (*)(int ) )&SIGWntHandler) == SIG_ERR)
+    cout << "signal(OSD::SetSignal) error\n";
+  if (signal (SIGILL,  (void (*)(int ) )&SIGWntHandler) == SIG_ERR)
+    cout << "signal(OSD::SetSignal) error\n";
+
+  // Set Ctrl-C and Ctrl-Break handler
+  fCtrlBrk = Standard_False;
+  SetConsoleCtrlHandler (&_osd_ctrl_break_handler, TRUE);
 
 #ifdef _MSC_VER
- if (fSETranslator) {
-   // use Structural Exception translator (one per thread)
-   _se_translator_function pOldSeFunc = _set_se_translator( TranslateSE );
- }
+  _se_translator_function pOldSeFunc = _set_se_translator (TranslateSE);
 #endif
 
- fFltExceptions = aFloatingSignal;
- if ( aFloatingSignal ) {
-   _controlfp ( 0, _OSD_FPX );          // JR add :
-   if ( first_time ) {
-//     cout << "SetSignal with floating point traps : " << hex << _controlfp(0,0) << dec << endl ;
-     first_time = 0 ;
-   }
- }
- else {
-   _controlfp ( _OSD_FPX , _OSD_FPX );          // JR add :
-   if ( first_time ) {
-//     cout << "SetSignal without floating point traps : " << hex << _controlfp(0,0) << dec << endl ;
-     first_time = 0 ;
-   }
- }
-
+  fFltExceptions = theFloatingSignal;
+  if (theFloatingSignal)
+  {
+    _controlfp (0, _OSD_FPX);        // JR add :
+  }
+  else {
+    _controlfp (_OSD_FPX, _OSD_FPX); // JR add :
+  }
 #endif
-
 }  // end OSD :: SetSignal
 
 //============================================================================
@@ -509,73 +480,64 @@ static BOOL WINAPI _osd_ctrl_break_handler ( DWORD dwCode ) {
 
 static LONG __fastcall _osd_raise ( DWORD dwCode, LPTSTR msg ) 
 {
-  if (  msg[ 0 ] == TEXT( '\x03' )  ) ++msg;
-
- switch ( dwCode ) {
-    
-  case EXCEPTION_ACCESS_VIOLATION:
-
-   OSD_Exception_ACCESS_VIOLATION :: Raise ( msg );
-
-  case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
-
-   OSD_Exception_ARRAY_BOUNDS_EXCEEDED :: Raise ( msg );
-
-  case EXCEPTION_DATATYPE_MISALIGNMENT:
-
-   Standard_ProgramError :: Raise ( msg );
-
-  case EXCEPTION_ILLEGAL_INSTRUCTION:
-
-   OSD_Exception_ILLEGAL_INSTRUCTION :: Raise ( msg );
-
-  case EXCEPTION_IN_PAGE_ERROR:
-
-   OSD_Exception_IN_PAGE_ERROR :: Raise ( msg );
-
-  case EXCEPTION_INT_DIVIDE_BY_ZERO:
-
-   Standard_DivideByZero :: Raise ( msg );
-
-  case EXCEPTION_INT_OVERFLOW:
-
-   OSD_Exception_INT_OVERFLOW :: Raise ( msg );
-
-  case EXCEPTION_INVALID_DISPOSITION:
-
-   OSD_Exception_INVALID_DISPOSITION :: Raise ( msg );
-
-  case EXCEPTION_NONCONTINUABLE_EXCEPTION:
-
-   OSD_Exception_NONCONTINUABLE_EXCEPTION :: Raise ( msg );
-
-  case EXCEPTION_PRIV_INSTRUCTION:
-
-   OSD_Exception_PRIV_INSTRUCTION :: Raise ( msg );
-
-  case EXCEPTION_STACK_OVERFLOW:
-
-   OSD_Exception_STACK_OVERFLOW :: Raise ( msg );
-    
-  case EXCEPTION_FLT_DIVIDE_BY_ZERO:
-       Standard_DivideByZero :: Raise ( msg );
-  case EXCEPTION_FLT_STACK_CHECK:
-  case EXCEPTION_FLT_OVERFLOW:
-       Standard_Overflow :: Raise ( msg );
-  case EXCEPTION_FLT_UNDERFLOW:
-       Standard_Underflow :: Raise ( msg );
-  case EXCEPTION_FLT_INVALID_OPERATION:
-  case EXCEPTION_FLT_DENORMAL_OPERAND:
-  case EXCEPTION_FLT_INEXACT_RESULT:
-  case STATUS_FLOAT_MULTIPLE_TRAPS:
-  case STATUS_FLOAT_MULTIPLE_FAULTS:
-       Standard_NumericError :: Raise ( msg );
-  default:
-    break;
- }  // end switch
-
- return EXCEPTION_EXECUTE_HANDLER;
-
+  if (msg[0] == TEXT('\x03')) ++msg;
+
+  switch (dwCode)
+  {
+    case EXCEPTION_ACCESS_VIOLATION:
+      OSD_Exception_ACCESS_VIOLATION::Raise (msg);
+      break;
+    case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
+      OSD_Exception_ARRAY_BOUNDS_EXCEEDED::Raise (msg);
+      break;
+    case EXCEPTION_DATATYPE_MISALIGNMENT:
+      Standard_ProgramError::Raise (msg);
+      break;
+    case EXCEPTION_ILLEGAL_INSTRUCTION:
+      OSD_Exception_ILLEGAL_INSTRUCTION::Raise (msg);
+      break;
+    case EXCEPTION_IN_PAGE_ERROR:
+      OSD_Exception_IN_PAGE_ERROR::Raise (msg);
+      break;
+    case EXCEPTION_INT_DIVIDE_BY_ZERO:
+      Standard_DivideByZero::Raise (msg);
+      break;
+    case EXCEPTION_INT_OVERFLOW:
+      OSD_Exception_INT_OVERFLOW::Raise (msg);
+      break;
+    case EXCEPTION_INVALID_DISPOSITION:
+      OSD_Exception_INVALID_DISPOSITION::Raise (msg);
+      break;
+    case EXCEPTION_NONCONTINUABLE_EXCEPTION:
+      OSD_Exception_NONCONTINUABLE_EXCEPTION::Raise (msg);
+      break;
+    case EXCEPTION_PRIV_INSTRUCTION:
+      OSD_Exception_PRIV_INSTRUCTION::Raise (msg);
+      break;
+    case EXCEPTION_STACK_OVERFLOW:
+      OSD_Exception_STACK_OVERFLOW::Raise (msg);
+      break;
+    case EXCEPTION_FLT_DIVIDE_BY_ZERO:
+      Standard_DivideByZero::Raise (msg);
+      break;
+    case EXCEPTION_FLT_STACK_CHECK:
+    case EXCEPTION_FLT_OVERFLOW:
+      Standard_Overflow::Raise (msg);
+      break;
+    case EXCEPTION_FLT_UNDERFLOW:
+      Standard_Underflow::Raise (msg);
+      break;
+    case EXCEPTION_FLT_INVALID_OPERATION:
+    case EXCEPTION_FLT_DENORMAL_OPERAND:
+    case EXCEPTION_FLT_INEXACT_RESULT:
+    case STATUS_FLOAT_MULTIPLE_TRAPS:
+    case STATUS_FLOAT_MULTIPLE_FAULTS:
+      Standard_NumericError::Raise (msg);
+      break;
+    default:
+      break;
+  }  // end switch
+  return EXCEPTION_EXECUTE_HANDLER;
 }  // end _osd_raise
 
 //============================================================================
@@ -677,34 +639,6 @@ LONG _osd_debug ( void ) {
 #undef __leave
 #endif
 
-//============================================================================
-//==== _debug_break 
-//============================================================================
-
-void _debug_break ( Standard_PCharacter msg ) {
-
- OSD_Environment    env ( "CSF_DEBUG_MODE" );
- Standard_Character buff[ 2048 ];
-
- env.Value ();
-
- if (  env.Failed ()  ) return;
-
- lstrcpy ( buff, msg );
- lstrcat (  buff, _TEXT( "\nExit to debugger ?" )  );
-
- if (  MessageBox (
-        NULL, buff, _TEXT( "DEBUG" ), MB_SYSTEMMODAL | MB_ICONQUESTION | MB_YESNO
-       ) == IDYES
- ) {
-  _osd_debug ();
-  DebugBreak ();
- }  // end if
-
-}  // end _debug_break
-
 // Must be there for compatibility with UNIX system code ----------------------
 
 //void OSD::Handler(const OSD_Signals aSig,
@@ -718,26 +652,3 @@ void OSD::SegvHandler(const OSD_Signals aSig,
                       const Standard_Address scp){}
 
 #endif // WNT
-
-
-//=======================================================================
-//function : UseSETranslator
-//purpose  : Defines whether to use _se_translator_function or
-//           SetUnhandledExceptionFilter and signal to catch system exceptions
-//=======================================================================
-
-void OSD::UseSETranslator( const Standard_Boolean
-#ifdef _MSC_VER
-                          useSE
-#endif
-                          )
-{
-#ifdef _MSC_VER
-  fSETranslator = useSE;
-#endif
-}
-
-Standard_Boolean OSD::UseSETranslator()
-{
-  return fSETranslator;
-}