Salome HOME
44da2fcd081f692414cb89fed6164d1ee5f06868
[modules/gui.git] / src / CASCatch / CASCatch_CatchSignals.cxx
1 // Copyright (C) 2007-2019  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 // File   : CASCatch_CatchSignals.cxx
24 // Author : Sergey RUIN, Open CASCADE S.A.S (sergey.ruin@opencascade.com)
25
26 #include "CASCatch_CatchSignals.hxx"
27 #include "CASCatch_Failure.hxx"  
28 #include "CASCatch_ErrorHandler.hxx"
29
30 #include <TCollection_AsciiString.hxx>
31
32 #define MAX_HANDLER_NUMBER 6
33
34 //================================================================================
35 /*! Public -
36  * \brief creates a CASCatch_CatchSignals
37  */
38 //================================================================================ 
39 CASCatch_CatchSignals::CASCatch_CatchSignals() 
40   : myIsActivated( Standard_False )
41 {
42   for ( Standard_Integer i = 0; i <= MAX_HANDLER_NUMBER; i++ )
43     mySigStates[i] = NULL;
44 }
45
46 #ifndef WIN32
47
48 //================================ UNIX part ==================================================
49
50 #include <OSD.hxx>
51 #include <OSD_WhoAmI.hxx>
52 #include <OSD_SIGHUP.hxx>
53 #include <OSD_SIGINT.hxx>
54 #include <OSD_SIGQUIT.hxx>
55 #include <OSD_SIGILL.hxx>
56 #include <OSD_SIGKILL.hxx>
57 #include <OSD_SIGBUS.hxx>
58 #include <OSD_SIGSEGV.hxx>
59 #include <OSD_SIGSYS.hxx>
60
61 typedef void (ACT_SIGIO_HANDLER)(void) ;
62 ACT_SIGIO_HANDLER *ADR_ACT_SIGIO_HANDLER = NULL ;
63
64 typedef void (* SIG_PFV) (int);
65
66 #ifdef SUN
67 # include <floatingpoint.h>
68 #endif
69
70 #ifdef SOLARIS
71 # include <floatingpoint.h>
72 # include <sys/machsig.h>
73 # include <stdlib.h>
74 # include <stdio.h>
75 #endif
76
77 #include <signal.h>
78 #include <sys/signal.h>
79
80 # include <stdlib.h>
81 # include <stdio.h>
82
83 #ifdef IRIX
84 # include <sigfpe.h>
85 # include <sys/siginfo.h>
86 #endif 
87
88
89 //================================================================================
90 /*! Private -
91  * \brief universal handler for signals
92  */
93 //================================================================================ 
94 static void Handler(const int theSig)
95 {
96   sigset_t set;
97   sigemptyset(&set);
98   sigaddset(&set, theSig);
99   sigprocmask(SIG_UNBLOCK, &set, NULL) ;
100
101   TCollection_AsciiString aMessage(theSig);  
102   aMessage+=" signal detected";
103  
104   CASCatch_Failure::Raise(aMessage.ToCString());
105 }
106
107
108 #ifdef SA_SIGINFO
109 //================================================================================
110 /*! Private -
111  * \brief  handler for SIGSEGV signal
112  */
113 //================================================================================ 
114 static void SegvHandler(const int, siginfo_t*, const Standard_Address)
115 {
116   sigset_t set;
117   sigemptyset(&set);
118   sigaddset(&set, SIGSEGV);
119   sigprocmask (SIG_UNBLOCK, &set, NULL); 
120
121   CASCatch_Failure::Raise("SIGSEGV detected");
122 }
123 #endif
124
125
126 //================================================================================
127 /*! Public -
128  * \brief activates a signals handling
129  */
130 //================================================================================ 
131 void CASCatch_CatchSignals::Activate() 
132 {  
133   if(myIsActivated) return;
134
135   struct sigaction act;
136
137   Standard_Integer i = 0;
138   for(; i<=MAX_HANDLER_NUMBER; i++)  
139     mySigStates[i] = new struct sigaction(); //Initialize structures
140
141   int stat;
142   act.sa_handler =  (SIG_PFV) &Handler ;
143   sigemptyset(&act.sa_mask) ;
144
145   stat = sigaction(SIGHUP,&act,(struct sigaction*)mySigStates[0]);   // ...... hangup
146   stat = sigaction(SIGFPE,&act,(struct sigaction*) mySigStates[1]);  // ...... floating point exception
147   stat = sigaction(SIGINT,&act,(struct sigaction*)mySigStates[2]);   // ...... interrupt
148   stat = sigaction(SIGQUIT,&act,(struct sigaction*)mySigStates[3]);  // ...... quit
149   stat = sigaction(SIGBUS,&act,(struct sigaction*)mySigStates[4]);   // ...... bus error
150   stat = sigaction(SIGILL,&act,(struct sigaction*)mySigStates[5]);   // ...... illegal instruction
151
152 #ifdef SA_RESTART
153   act.sa_flags   = SA_RESTART ;
154 #else
155   act.sa_flags   = 0 ;
156 #endif
157   act.sa_handler = (SIG_PFV) &SegvHandler ;
158
159 #ifdef SA_SIGINFO       // OSF,SOLARIS,IRIX
160   act.sa_flags = act.sa_flags | SA_SIGINFO ;
161 # ifdef SOLARIS
162   act.sa_sigaction = (void(*)(int, siginfo_t *, void*)) &SegvHandler ;
163 # endif
164 #endif
165
166   stat = sigaction( SIGSEGV , &act , (struct sigaction*)mySigStates[6]);    // ...... segmentation violation
167
168   myIsActivated = Standard_True;
169 }
170
171
172 //================================================================================
173 /*! Public -
174  * \brief deactivates a signals handling
175  */
176 //================================================================================
177 void CASCatch_CatchSignals::Deactivate() 
178 {
179   if(!myIsActivated) return;
180
181   struct sigaction oact;
182   int stat;
183
184   stat = sigaction(SIGHUP,(struct sigaction*)mySigStates[0],&oact);   // ...... hangup
185   stat = sigaction(SIGFPE,(struct sigaction*)mySigStates[1],&oact);   // ...... floating point exception
186   stat = sigaction(SIGINT,(struct sigaction*)mySigStates[2],&oact);   // ...... interrupt
187   stat = sigaction(SIGQUIT,(struct sigaction*)mySigStates[3],&oact);  // ...... quit
188   stat = sigaction(SIGBUS,(struct sigaction*)mySigStates[4],&oact);   // ...... bus error
189   stat = sigaction(SIGILL,(struct sigaction*)mySigStates[5],&oact);   // ...... illegal instruction
190   stat = sigaction(SIGSEGV,(struct sigaction*)mySigStates[6],&oact);  // ...... segmentation violation
191
192
193   Standard_Integer i = 0;
194   for(; i<=MAX_HANDLER_NUMBER; i++)
195     delete (struct sigaction*)mySigStates[i];
196
197   myIsActivated = Standard_False;
198 }
199
200
201
202 #else
203 //====================================== WIN32 part ====================================================
204 #include <OSD_WNT.hxx>
205
206 #include <process.h>
207 #include <signal.h>
208 #include <float.h>
209
210 #define _OSD_FPX ( _EM_DENORMAL | _EM_INEXACT | _EM_UNDERFLOW | _EM_ZERODIVIDE | _EM_OVERFLOW) //Mask these exceptions
211
212 //================================================================================
213 /*! Private -
214  * \brief handler for unexpected exceptions
215  */
216 //================================================================================
217 static Standard_Integer WntHandler(const Standard_Address theExceptionInfo) 
218 {
219   LPEXCEPTION_POINTERS lpXP = ( LPEXCEPTION_POINTERS )theExceptionInfo;
220   DWORD                dwExceptionCode = lpXP -> ExceptionRecord -> ExceptionCode;
221
222   TCollection_AsciiString aMessage((Standard_Integer)dwExceptionCode);  
223   aMessage+=" Exception code - unexpected exception";
224
225   CASCatch_Failure::Raise(aMessage.ToCString());
226
227   return EXCEPTION_EXECUTE_HANDLER;
228 }
229
230 void SIGWntHandler(int , int ) ;
231 static void (*SIGWNTHANDLER)(int) = ( void (*)(int) ) ( &SIGWntHandler ) ;
232
233
234 //================================================================================
235 /*! Private -
236  * \brief handler for signals
237  */
238 //================================================================================
239 static void SIGWntHandler(const int signum , const int theCode)
240 {
241
242   void (*OLDSIGWNTHANDLER)(int) ;  
243   switch( signum ) { 
244   case SIGFPE : 
245     _fpreset() ;
246     _clearfp() ; 
247     _controlfp ( _OSD_FPX, _MCW_EM ); 
248     OLDSIGWNTHANDLER = signal( signum , SIGWNTHANDLER ); 
249
250     if(theCode == _FPE_UNDERFLOW || theCode == _FPE_INEXACT) return;
251     CASCatch_Failure::Raise ("Floating point error"); 
252     break;
253   case SIGSEGV : 
254     OLDSIGWNTHANDLER = signal( signum , SIGWNTHANDLER );
255     CASCatch_Failure::Raise("Access violation"); 
256     break; 
257   case SIGILL : 
258     OLDSIGWNTHANDLER = signal( signum , SIGWNTHANDLER );
259     CASCatch_Failure::Raise("Illegal instruction" ); 
260     break; 
261   }
262 }
263
264
265 //================================================================================
266 /*! Public -
267  * \brief activates a signals handling
268  */
269 //================================================================================ 
270 void CASCatch_CatchSignals::Activate() 
271 {
272   if(myIsActivated) return;
273
274   mySigStates[0] = SetUnhandledExceptionFilter (( LPTOP_LEVEL_EXCEPTION_FILTER )&WntHandler);
275
276   myFloatOpWord = _controlfp(0, 0);
277   _controlfp ( _OSD_FPX, _MCW_EM );  //Enable floating point exceptions
278
279   mySigStates[1] = signal( SIGSEGV , SIGWNTHANDLER );
280   mySigStates[2] = signal( SIGFPE , SIGWNTHANDLER );
281   mySigStates[3] = signal( SIGILL , SIGWNTHANDLER );
282
283   myIsActivated = Standard_True;
284 }
285
286 //================================================================================
287 /*! Public -
288  * \brief deactivates a signals handling
289  */
290 //================================================================================
291 void CASCatch_CatchSignals::Deactivate() 
292 {
293   if(!myIsActivated) return;
294
295   SetUnhandledExceptionFilter (( LPTOP_LEVEL_EXCEPTION_FILTER )mySigStates[0]);
296
297   _controlfp ( myFloatOpWord, _MCW_EM );
298
299   signal( SIGSEGV ,  ( void (*)(int) )mySigStates[1]);
300   signal( SIGFPE , ( void (*)(int) )mySigStates[2]);
301   signal( SIGILL , ( void (*)(int) )mySigStates[3]);
302
303   Standard_Integer i = 0;
304   for(; i<=MAX_HANDLER_NUMBER; i++)
305     mySigStates[i] = NULL;
306   
307   myIsActivated = Standard_False;
308 }
309
310 #endif
311
312 //================================================================================
313 /*! Private -
314  * \brief deactivates a signals handling
315  */
316 //================================================================================
317 void CASCatch_CatchSignals::Destroy() 
318 {
319   if(myIsActivated) Deactivate();
320 }
321