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