Salome HOME
90f90d55b2631516fa1d6bbbd7fa4dc628808888
[modules/gui.git] / src / CASCatch / CASCatch_CatchSignals.cxx
1 //  Copyright (C) 2007-2008  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.
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 // File   : CASCatch_CatchSignals.cxx
23 // Author : Sergey RUIN, Open CASCADE S.A.S (sergey.ruin@opencascade.com)
24 //
25 #include "CASCatch_CatchSignals.hxx"
26
27 #include "CASCatch_Failure.hxx"  
28 #include "CASCatch_ErrorHandler.hxx"
29 #include <TCollection_AsciiString.hxx>
30
31 #define MAX_HANDLER_NUMBER 6
32
33
34 //================================================================================
35 /*! Public -
36  * \brief creates a CASCatch_CatchSignals
37  */
38 //================================================================================ 
39 CASCatch_CatchSignals::CASCatch_CatchSignals() 
40      :myIsActivated(Standard_False)
41 {
42
43   Standard_Integer i = 0;
44   for(; i<=MAX_HANDLER_NUMBER; i++)
45     mySigStates[i] = NULL;
46 }
47
48 #ifndef WNT
49
50 //================================ UNIX part ==================================================
51
52 #include <OSD.hxx>
53 #include <OSD_WhoAmI.hxx>
54 #include <OSD_SIGHUP.hxx>
55 #include <OSD_SIGINT.hxx>
56 #include <OSD_SIGQUIT.hxx>
57 #include <OSD_SIGILL.hxx>
58 #include <OSD_SIGKILL.hxx>
59 #include <OSD_SIGBUS.hxx>
60 #include <OSD_SIGSEGV.hxx>
61 #include <OSD_SIGSYS.hxx>
62 #ifndef LIN
63 #include <exception.h>
64 #endif
65
66 //==============================
67 typedef void (ACT_SIGIO_HANDLER)(void) ;
68
69 ACT_SIGIO_HANDLER *ADR_ACT_SIGIO_HANDLER = NULL ;
70
71 typedef void (* SIG_PFV) (int);
72
73 #ifdef SUN
74 # include <floatingpoint.h>
75 #endif
76
77 #ifdef SOLARIS
78 # include <floatingpoint.h>
79 # include <sys/machsig.h>
80 # include <stdlib.h>
81 # include <stdio.h>
82 #endif
83
84 #include <signal.h>
85 #include <sys/signal.h>
86
87 #ifdef LIN
88 # include <stdlib.h>
89 # include <stdio.h>
90 #else
91 # ifdef SA_SIGINFO 
92 #   ifndef AIX
93 # include <sys/siginfo.h>
94 #    endif
95 # endif
96 #endif
97
98
99 #ifdef IRIX
100 # include <sigfpe.h>
101 # include <sys/siginfo.h>
102 #endif 
103
104
105 //================================================================================
106 /*! Private -
107  * \brief universal handler for signals
108  */
109 //================================================================================ 
110 static void Handler(const OSD_Signals theSig, const OSD_Signals)
111 {
112   sigset_t set;
113   sigemptyset(&set);
114   sigaddset(&set, theSig);
115   sigprocmask(SIG_UNBLOCK, &set, NULL) ;
116
117   TCollection_AsciiString aMessage(theSig);  
118   aMessage+=" signal detected";
119  
120   CASCatch_Failure::Raise(aMessage.ToCString());
121 }
122
123
124 #ifdef SA_SIGINFO
125 //================================================================================
126 /*! Private -
127  * \brief  handler for SIGSEGV signal
128  */
129 //================================================================================ 
130 static void SegvHandler(const OSD_Signals, const Standard_Address, const Standard_Address)
131 {
132   sigset_t set;
133   sigemptyset(&set);
134   sigaddset(&set, SIGSEGV);
135   sigprocmask (SIG_UNBLOCK, &set, NULL); 
136
137   CASCatch_Failure::Raise("SIGSEGV detected");
138 }
139 #endif
140
141
142 //================================================================================
143 /*! Public -
144  * \brief activates a signals handling
145  */
146 //================================================================================ 
147 void CASCatch_CatchSignals::Activate() 
148 {  
149   if(myIsActivated) return;
150
151   struct sigaction act;
152
153   Standard_Integer i = 0;
154   for(; i<=MAX_HANDLER_NUMBER; i++)  
155     mySigStates[i] = new struct sigaction(); //Initialize structures
156
157   int stat;
158   act.sa_handler =  (SIG_PFV) &Handler ;
159   sigemptyset(&act.sa_mask) ;
160
161
162   stat = sigaction(SIGHUP,&act,(struct sigaction*)mySigStates[0]);    // ...... hangup
163   stat = sigaction(SIGFPE,&act,(struct sigaction*) mySigStates[1]);   // ...... floating point exception
164   stat = sigaction(SIGINT,&act,(struct sigaction*)mySigStates[2]);   // ...... interrupt
165   stat = sigaction(SIGQUIT,&act,(struct sigaction*)mySigStates[3]);  // ...... quit
166   stat = sigaction(SIGBUS,&act,(struct sigaction*)mySigStates[4]);   // ...... bus error
167   stat = sigaction(SIGILL,&act,(struct sigaction*)mySigStates[5]);   // ...... illegal instruction
168
169 #ifdef SA_RESTART
170   act.sa_flags   = SA_RESTART ;
171 #else
172   act.sa_flags   = 0 ;
173 #endif
174   act.sa_handler = (SIG_PFV) &SegvHandler ;
175
176 #ifdef SA_SIGINFO       // OSF,SOLARIS,IRIX
177   act.sa_flags = act.sa_flags | SA_SIGINFO ;
178 # ifdef SOLARIS
179   act.sa_sigaction = (void(*)(int, siginfo_t *, void*)) &SegvHandler ;
180 # endif
181 #endif
182
183   stat = sigaction( SIGSEGV , &act , (struct sigaction*)mySigStates[6]);    // ...... segmentation violation
184
185   myIsActivated = Standard_True;
186 }
187
188
189 //================================================================================
190 /*! Public -
191  * \brief deactivates a signals handling
192  */
193 //================================================================================
194 void CASCatch_CatchSignals::Deactivate() 
195 {
196   if(!myIsActivated) return;
197
198   struct sigaction oact;
199   int stat;
200
201   stat = sigaction(SIGHUP,(struct sigaction*)mySigStates[0],&oact);   // ...... hangup
202   stat = sigaction(SIGFPE,(struct sigaction*)mySigStates[1],&oact);   // ...... floating point exception
203   stat = sigaction(SIGINT,(struct sigaction*)mySigStates[2],&oact);   // ...... interrupt
204   stat = sigaction(SIGQUIT,(struct sigaction*)mySigStates[3],&oact);  // ...... quit
205   stat = sigaction(SIGBUS,(struct sigaction*)mySigStates[4],&oact);   // ...... bus error
206   stat = sigaction(SIGILL,(struct sigaction*)mySigStates[5],&oact);   // ...... illegal instruction
207   stat = sigaction(SIGSEGV,(struct sigaction*)mySigStates[6],&oact);  // ...... segmentation violation
208
209
210   Standard_Integer i = 0;
211   for(; i<=MAX_HANDLER_NUMBER; i++)
212     delete (struct sigaction*)mySigStates[i];
213
214   myIsActivated = Standard_False;
215 }
216
217
218
219 #else
220 //====================================== WNT part ====================================================
221 #include <OSD_WNT_1.hxx>
222
223 #include <process.h>
224 #include <signal.h>
225 #include <float.h>
226
227 #define _OSD_FPX ( _EM_DENORMAL | _EM_INEXACT | _EM_UNDERFLOW | _EM_ZERODIVIDE | _EM_OVERFLOW) //Mask these exceptions
228
229 //================================================================================
230 /*! Private -
231  * \brief handler for unexpected exceptions
232  */
233 //================================================================================
234 static Standard_Integer WntHandler(const Standard_Address theExceptionInfo) 
235 {
236   LPEXCEPTION_POINTERS lpXP = ( LPEXCEPTION_POINTERS )theExceptionInfo;
237   DWORD                dwExceptionCode = lpXP -> ExceptionRecord -> ExceptionCode;
238
239   TCollection_AsciiString aMessage((Standard_Integer)dwExceptionCode);  
240   aMessage+=" Exception code - unexpected exception";
241
242   CASCatch_Failure::Raise(aMessage.ToCString());
243
244   return EXCEPTION_EXECUTE_HANDLER;
245 }
246
247 void SIGWntHandler(int , int ) ;
248 static void (*SIGWNTHANDLER)(int) = ( void (*)(int) ) ( &SIGWntHandler ) ;
249
250
251 //================================================================================
252 /*! Private -
253  * \brief handler for signals
254  */
255 //================================================================================
256 static void SIGWntHandler(const int signum , const int theCode)
257 {
258
259   void (*OLDSIGWNTHANDLER)(int) ;  
260   switch( signum ) { 
261   case SIGFPE : 
262     _fpreset() ;
263     _clearfp() ; 
264     _controlfp ( _OSD_FPX, _MCW_EM ); 
265     OLDSIGWNTHANDLER = signal( signum , SIGWNTHANDLER ); 
266
267     if(theCode == _FPE_UNDERFLOW || theCode == _FPE_INEXACT) return;
268     CASCatch_Failure::Raise ("Floating point error"); 
269     break;
270   case SIGSEGV : 
271     OLDSIGWNTHANDLER = signal( signum , SIGWNTHANDLER );
272     CASCatch_Failure::Raise("Access violation"); 
273     break; 
274   case SIGILL : 
275     OLDSIGWNTHANDLER = signal( signum , SIGWNTHANDLER );
276     CASCatch_Failure::Raise("Illegal instruction" ); 
277     break; 
278   }
279 }
280
281
282 //================================================================================
283 /*! Public -
284  * \brief activates a signals handling
285  */
286 //================================================================================ 
287 void CASCatch_CatchSignals::Activate() 
288 {
289   if(myIsActivated) return;
290
291   mySigStates[0] = SetUnhandledExceptionFilter (( LPTOP_LEVEL_EXCEPTION_FILTER )&WntHandler);
292
293   myFloatOpWord = _controlfp(0, 0);
294   _controlfp ( _OSD_FPX, _MCW_EM );  //Enable floating point exceptions
295
296   mySigStates[1] = signal( SIGSEGV , SIGWNTHANDLER );
297   mySigStates[2] = signal( SIGFPE , SIGWNTHANDLER );
298   mySigStates[3] = signal( SIGILL , SIGWNTHANDLER );
299
300   myIsActivated = Standard_True;
301 }
302
303 //================================================================================
304 /*! Public -
305  * \brief deactivates a signals handling
306  */
307 //================================================================================
308 void CASCatch_CatchSignals::Deactivate() 
309 {
310   if(!myIsActivated) return;
311
312   SetUnhandledExceptionFilter (( LPTOP_LEVEL_EXCEPTION_FILTER )mySigStates[0]);
313
314   _controlfp ( myFloatOpWord, _MCW_EM );
315
316   signal( SIGSEGV ,  ( void (*)(int) )mySigStates[1]);
317   signal( SIGFPE , ( void (*)(int) )mySigStates[2]);
318   signal( SIGILL , ( void (*)(int) )mySigStates[3]);
319
320   Standard_Integer i = 0;
321   for(; i<=MAX_HANDLER_NUMBER; i++)
322     mySigStates[i] = NULL;
323   
324   myIsActivated = Standard_False;
325 }
326
327 #endif
328
329 //================================================================================
330 /*! Private -
331  * \brief deactivates a signals handling
332  */
333 //================================================================================
334 void CASCatch_CatchSignals::Destroy() 
335 {
336   if(myIsActivated) Deactivate();
337 }
338