1 /*
2 * xerrorhandler.cpp
3 *
4 * Copyright (C) 2001 J. "MUFTI" Scheurich
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program (see the file "COPYING" for details); if
17 * not, write to the Free Software Foundation, Inc., 675 Mass Ave,
18 * Cambridge, MA 02139, USA.
19 *
20 * Additional License - if you need another License 8-)
21
22 Permission is hereby granted, free of charge, to any person obtaining a
23 copy of this file, to deal in this file without restriction, including
24 without limitation the rights to use, copy, modify, merge, publish,
25 distribute, and/or sell copies of this file, and to permit persons
26 to whom this file is furnished to do so, provided that the above
27 copyright notice(s) and this permission notice appear in all copies of
28 this file and that both the above copyright notice(s) and this
29 permission notice appear in supporting documentation.
30
31 THIS FILE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
32 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
34 OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
35 HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
36 INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
37 FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
38 NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
39 WITH THE USE OR PERFORMANCE OF THIS FILE.
40
41 Except as contained in this notice, the name of a copyright holder
42 shall not be used in advertising or otherwise to promote the sale, use
43 or other dealings in this Software without prior written authorization
44 of the copyright holder.
45 */
46
47 /*
48 * tries to catch signals and X11 errors and
49 * try to save the content in case of crashes
50 */
51
52 #include "xerrorhandler.h"
53 #include "stdafx.h"
54 #include "MainWindow.h"
55 #include "DuneApp.h"
56 #include "swt.h"
57 #include "maxpath.h"
58
coredump(void)59 void coredump(void)
60 {
61 int *nix=NULL;
62 nix[0]=1;
63 }
64
65 static int normal_exit=0;
66 #ifdef _WIN32
67 extern "C" {
68 int popupConsole();
69 }
70 #endif
71
setNormalExit(void)72 void setNormalExit(void)
73 {
74 normal_exit=1;
75 }
76
normalExit(int status)77 void normalExit(int status)
78 {
79 myflushall();
80 #ifdef _WIN32
81 if (popupConsole()) {
82 printf("Press Enter to Exit:");
83 getchar();
84 }
85 #endif
86 setNormalExit();
87 exit(status);
88 }
89
90 #ifdef EXIT_HANDLER
exit_handler(void)91 void exit_handler(void)
92 {
93 // if (normal_exit==0)
94 // TheApp->emergency_rescue();
95 }
96 #endif
97
98 #ifndef HAVE_WANT_CORE
99 # ifdef HAVE_NEW_NEW_HANDLER
100 # ifndef HAVE_NEW_HANDLER
101 # define HAVE_NEW_HANDLER 1
102 # endif
103 # endif
104
105 # ifdef HAVE_NEW_HANDLER
106 # ifdef HAVE_NEW_NEW_HANDLER
107 # include <new>
108 # else
109 # include <new.h>
110 # endif
111
dune_new_handler(void)112 static void dune_new_handler(void)
113 {
114 TheApp->emergency_rescue();
115 // normalExit(1);
116 }
117 # endif
118 #endif
119
120 /*
121 * Try to save scenegraphs into files
122 */
123
124 #ifdef _WIN32
125 #include <process.h>
126 #include "stdafx.h"
127 #include "Windows.h"
128 # define sleep(x)
129 # define myMessageBox(x) MessageBox(NULL,x,"White_dune",MB_ICONINFORMATION);
130 #else
131 # define mywriteerr(x) while(write(2,x,mystrlen(x)) == -1);
132 #endif
133
134
135 char* home;
136
emergency_rescue(int sig)137 int DuneApp::emergency_rescue(int sig)
138 #ifdef __clang__
139 # if __MAGEIA__
140 __attribute__((noreturn))
141 # endif
142 # if defined __FreeBSD__ || defined __DragonFly__
143 __attribute__((noreturn))
144 # endif
145 # ifdef MACOSX
146 __attribute__((noreturn))
147 # endif
148 #endif
149 {
150 int filenum=0;
151
152 int console;
153
154 myflushall();
155 swUploadCleanupPasswd(m_upload);
156
157 #ifndef _WIN32
158 console=open("/dev/console",O_WRONLY | O_NONBLOCK);
159 if (console==-1)
160 console=2;
161
162 if ((sig != SIGPIPE) && !isatty(0)) {
163 mywritestr(console,"white_dune: Internal Crash !\nwhite_dune: Try to save Files\n");
164 mywriteerr("Internal Crash !\a\n Try to save Files\n");
165 }
166 #endif
167 for (List<MainWindow *>::Iterator *i=m_windows.first(); i; i=i->next())
168 {
169 char mypath[MY_MAX_PATH+1];
170 char filename[MY_MAX_PATH+1];
171 struct stat fileStat;
172 bool x3d = i->item()->GetScene()->isX3d();
173 const char *ext = "wrl";
174 if (x3d)
175 ext = "x3dv";
176 int flags = TEMP_SAVE | (x3d ? X3DV : 0);
177 int f = -1;
178 do {
179 filenum++;
180 mysnprintf(filename,MY_MAX_PATH,".dune_crash_%d_%d.%s",getpid(),
181 filenum, ext);
182 #ifdef _WIN32
183 mysnprintf(mypath,MY_MAX_PATH,"%s%s\\%s",getenv("HOMEDRIVE"),
184 getenv("HOMEPATH"),filename);
185 #else
186 mysnprintf(mypath,MY_MAX_PATH,"%s/%s",home,filename);
187 #endif
188 f = open(mypath, O_WRONLY | O_CREAT
189 /* writing with O_SYNC is too slow on most systems... */
190 # ifdef PARANOIA
191 # ifdef O_SYNC
192 | O_SYNC
193 # endif
194 # endif
195 #ifdef _WIN32
196 ,_S_IREAD | _S_IWRITE);
197 #else
198 ,S_IRUSR | S_IWUSR);
199 #endif
200 } while (f == -1);
201 #ifndef _WIN32
202 mywritef(console, "%s: %s\n", mypath, strerror(errno));
203 mywritef(console,"white_dune: %s: %s\n", mypath, strerror(errno));
204 #endif
205 int writeError = false;
206 if (i->item()->GetScene()->write(f, mypath, flags) < 0)
207 writeError = true;
208 if (!writeError && swTruncateClose(f))
209 writeError = true;
210 if (writeError)
211 {
212 mywritef(console, "write %s: %s\n", mypath, strerror(errno));
213 mywritef(console," error write white_dune: %s: %s\n", mypath,
214 strerror(errno));
215 }
216 else
217 {
218 TheApp->setCrashFile(i->item()->GetScene()->getPath());
219 TheApp->AddToRecentFiles(mypath);
220 TheApp->SaveRecentFileList();
221 TheApp->SavePreferences();
222 #ifdef _WIN32
223 char message[1024];
224 mysnprintf(message,1023,"file successfully written to %s",mypath);
225 myMessageBox(message);
226 #else
227 mywritestr(console,"white_dune: write successful to ");
228 mywritestr(console,mypath);
229 mywritestr(console,"\n");
230 #endif
231 }
232 if (TheApp->returnTracker())
233 {
234 #ifndef _WIN32
235 mywritestr(console,"white_dune: tracker stopped successfully\n");
236 mywritestr(2,"tracker stopped successfully\n");
237 #endif
238 }
239 }
240 #ifndef _WIN32
241 if ((filenum==0) && ((sig != SIGPIPE) && !isatty(0)))
242 {
243 mywritestr(console, "white_dune: Nothing to save anymore\n");
244 mywriteerr("Nothing to save anymore\n");
245 }
246 #endif
247 return filenum;
248 }
249
250 #ifdef _WIN32
251
init_handlers(void)252 void init_handlers(void)
253 {
254 # ifndef HAVE_WANT_CORE
255 # ifdef HAVE_NEW_HANDLER
256 # ifdef HAVE_NEW_NEW_HANDLER
257 std::set_new_handler(dune_new_handler);
258 # else
259 set_new_handler(dune_new_handler);
260 # endif
261 # endif
262 # endif
263 return;
264 }
265
266 #else
267
268 /*
269 * Handler for nofatal X11 Errors: you ignore them
270 */
271
nofatal_handler(Display * display,XErrorEvent * xerrorevent)272 int nofatal_handler(Display *display, XErrorEvent *xerrorevent)
273 {
274 static int numberX11Errors = 0;
275 int limit = TheApp->GetX11ErrorsLimit();
276 numberX11Errors++;
277 if ((limit == -1) || (numberX11Errors <= limit))
278 {
279 /* so what ?*/
280 char errortext[1025];
281
282 mywriteerr("nofatal X11 Error ignored\n");
283 XGetErrorText(display,xerrorevent->error_code,errortext,1024);
284 mywriteerr(errortext);
285 mywriteerr("\n");
286 }
287 else if (numberX11Errors == (limit + 1) && limit != 0)
288 mywriteerr("X11ErrorsLimit (see $HOME/.dunerc) exceeded\n");
289 return(1);
290 }
291
292 /*
293 * Handler for fatal X11 Errors: try to save files
294 */
295
fatal_handler(Display * display)296 int fatal_handler(Display *display)
297 {
298 TheApp->emergency_rescue();
299 // normalExit(2);
300 return(0);
301 }
302
303 /*
304 * Handler for fatal Xt Errors: try to save files
305 */
306
fatal_xthandler(char * message)307 void fatal_xthandler(char* message)
308 {
309 bool exitFlag = true;
310 // the following error is (hopefully) not really fatal for white_dune
311 if (strcmp(message,
312 "XtPopdown requires a subclass of shellWidgetClass") == 0)
313 exitFlag = false;
314 // no file to save, not really a fatal problem ?
315 if (exitFlag)
316 if (TheApp->emergency_rescue() == 0)
317 exitFlag = false;
318 if (exitFlag)
319 {
320 mywriteerr(message);
321 mywriteerr("\n");
322 // normalExit(2);
323 }
324 }
325
326
327 /*
328 * Handler for dangerous Unix Signals: try to save files
329 */
330
331 volatile int fatal_error_in_progress = 0;
332
333 #ifdef HAVE_SIGNAL_INT
signal_fatal_handler(int sig)334 void signal_fatal_handler(int sig)
335 {
336 # ifndef HAVE_WANT_CORE
337 signal (sig, SIG_IGN);
338 if (!fatal_error_in_progress)
339 {
340 fatal_error_in_progress = 1;
341 TheApp->emergency_rescue(sig);
342 signal (sig, SIG_DFL);
343 mywritef(2,"killed by signal %d\n",sig);
344 raise (sig);
345 }
346 # endif
347 }
348 # else
signal_fatal_handler()349 void signal_fatal_handler()
350 {
351 # ifndef HAVE_WANT_CORE
352 for (int i=1;i<=64;i++)
353 signal (i, SIG_IGN);
354 if (!fatal_error_in_progress)
355 {
356 fatal_error_in_progress = 1;
357 TheApp->emergency_rescue();
358 signal (SIGTERM, SIG_DFL);
359 raise (SIGTERM);
360 }
361 # endif
362 }
363 #endif
364
365 /*
366 * Initalize X11 and Unix Signal Handlers
367 */
368
369 # ifndef TRUE
370 # define TRUE 1
371 # define FALSE 0
372 # endif
373
init_handlers(void)374 void init_handlers(void)
375 {
376 int dangerous_signals[65];
377
378 /* initialise path to $HOME for usage in handler */
379 home=getenv("HOME");
380
381 #ifdef EXIT_HANDLER
382 atexit(&exit_handler);
383 #endif
384 # ifdef HAVE_NEW_HANDLER
385 # ifdef HAVE_NEW_NEW_HANDLER
386 std::set_new_handler(dune_new_handler);
387 #else
388 set_new_handler(dune_new_handler);
389 # endif
390 # endif
391 XSetErrorHandler(&nofatal_handler);
392 XSetIOErrorHandler(&fatal_handler);
393 // XtSetErrorHandler(&fatal_xthandler);
394 for (int i=1;i<=32;i++)
395 dangerous_signals[i]=TRUE;
396
397 /* list of not dangerous signals */
398 dangerous_signals[SIGCHLD]=FALSE;
399 dangerous_signals[SIGWINCH]=FALSE;
400 dangerous_signals[SIGURG]=FALSE;
401 dangerous_signals[SIGSTOP]=FALSE;
402 dangerous_signals[SIGTSTP]=FALSE;
403 dangerous_signals[SIGCONT]=FALSE;
404 dangerous_signals[SIGTTIN]=FALSE;
405 dangerous_signals[SIGTTOU]=FALSE;
406 # ifdef SIGCKPT
407 dangerous_signals[SIGCKPT]=FALSE;
408 # endif
409 # ifdef SIGRESTART
410 dangerous_signals[SIGRESTART]=FALSE;
411 # endif
412 /*
413 dangerous_signals[SIGPWR]=FALSE;
414 */
415
416 /* handle "dangerous Signals */
417 for (int i=1;i<=32;i++)
418 if (dangerous_signals[i]==TRUE)
419 signal(i,&signal_fatal_handler);
420
421 /* ignore CTRL-C interrupts */
422 signal(SIGINT,SIG_IGN);
423
424 /* handle known interrupts > 32 */
425 # ifdef SIGRTMIN
426 signal(SIGRTMIN,&signal_fatal_handler);
427 # endif
428 # ifdef SIGRTMAX
429 # ifdef __linux__
430 # ifdef HAVE_GNUC_ECGS_2_8
431 signal(SIGRTMAX,&signal_fatal_handler);
432 # endif
433 # else
434 signal(SIGRTMAX,&signal_fatal_handler);
435 # endif
436 # endif
437 }
438 #endif
439
440 #ifdef HAVE_FPU_ENABLE_INTERRUPTS
441
442 # ifdef HAVE_FPU_SETCW
443 # include <fpu_control.h>
444 # endif
445
446 # ifdef HAVE_HANDLE_SIGFPES
447 # include <sigfpe.h>
448 # endif
449
fpu_enable_interrupts(void)450 void fpu_enable_interrupts(void)
451 {
452
453 # ifdef HAVE_FPU_SETCW
454 unsigned int mask = _FPU_MASK_IM |
455 _FPU_MASK_DM |
456 _FPU_MASK_ZM |
457 _FPU_MASK_PM |
458 _FPU_MASK_UM |
459 _FPU_MASK_OM ;
460 mask=~mask & _FPU_DEFAULT;
461 _FPU_SETCW(mask);
462 # endif
463
464 # ifdef HAVE_HANDLE_SIGFPES
465 sigfpe_[_UNDERFL].abort =1;
466 sigfpe_[_OVERFL].abort =1;
467 sigfpe_[_INVALID].abort =1;
468 sigfpe_[_INT_OVERFL].abort=1;
469 sigfpe_[_DIVZERO].abort =1;
470
471 unsigned int mask = /* _EN_UNDERFL | */
472 _EN_OVERFL |
473 _EN_DIVZERO |
474 _EN_INVALID |
475 _EN_INT_OVERFL;
476 handle_sigfpes(_ON,mask,0,0,0);
477
478 }
479
480 # endif
481
482 #endif
483
484
485