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