update dev300-m57
[ooovba.git] / sal / osl / unx / signal.c
blob4b7dd6b72069c5ac502bb352438391d348abd690
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: signal.c,v $
10 * $Revision: 1.37 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
32 /* system headers */
33 #include "system.h"
35 #define MAX_STACK_FRAMES 256
37 #if defined( MACOSX )
39 #if defined( INTEL )
40 #include "backtrace.h"
41 #define INCLUDE_BACKTRACE
42 #define STACKTYPE "MacOsX_X86"
43 #endif /* INTEL */
45 #endif /* MACOSX */
47 #ifdef LINUX
48 #include <execinfo.h>
49 #define INCLUDE_BACKTRACE
50 #define STACKTYPE "Linux"
51 #endif
53 #ifdef SOLARIS
55 #include "backtrace.h"
56 #define INCLUDE_BACKTRACE
58 #if defined( SPARC )
59 #define STACKTYPE "Solaris_Sparc"
60 #elif defined( INTEL )
61 #define STACKTYPE "Solaris_X86"
62 #else
63 #define STACKTYPE "Solaris_Unknown"
64 #endif
66 #endif /* defined SOLARIS */
68 #include <osl/diagnose.h>
69 #include <osl/mutex.h>
70 #include <osl/signal.h>
71 #include <osl/process.h>
72 #include <osl/thread.h>
73 #include <rtl/bootstrap.h>
74 #include <rtl/digest.h>
76 #include "file_path_helper.h"
78 #define ACT_IGNORE 1
79 #define ACT_ABORT 2
80 #define ACT_EXIT 3
81 #define ACT_SYSTEM 4
82 #define ACT_HIDE 5
84 #define MAX_PATH_LEN 2048
86 typedef struct _oslSignalHandlerImpl
88 oslSignalHandlerFunction Handler;
89 void* pData;
90 struct _oslSignalHandlerImpl* pNext;
91 } oslSignalHandlerImpl;
93 static struct SignalAction
95 int Signal;
96 int Action;
97 void (*Handler)(int);
98 } Signals[] =
100 { SIGHUP, ACT_IGNORE, NULL }, /* hangup */
101 { SIGINT, ACT_EXIT, NULL }, /* interrupt (rubout) */
102 { SIGQUIT, ACT_EXIT, NULL }, /* quit (ASCII FS) */
103 { SIGILL, ACT_SYSTEM, NULL }, /* illegal instruction (not reset when caught) */
104 /* changed from ACT_ABOUT to ACT_SYSTEM to try and get collector to run*/
105 { SIGTRAP, ACT_ABORT, NULL }, /* trace trap (not reset when caught) */
106 #if ( SIGIOT != SIGABRT )
107 { SIGIOT, ACT_ABORT, NULL }, /* IOT instruction */
108 #endif
109 { SIGABRT, ACT_ABORT, NULL }, /* used by abort, replace SIGIOT in the future */
110 #ifdef SIGEMT
111 { SIGEMT, ACT_SYSTEM, NULL }, /* EMT instruction */
112 /* changed from ACT_ABORT to ACT_SYSTEM to remove handler*/
113 /* SIGEMT may also be used by the profiler - so it is probably not a good
114 plan to have the new handler use this signal*/
115 #endif
116 { SIGFPE, ACT_ABORT, NULL }, /* floating point exception */
117 { SIGKILL, ACT_SYSTEM, NULL }, /* kill (cannot be caught or ignored) */
118 { SIGBUS, ACT_ABORT, NULL }, /* bus error */
119 { SIGSEGV, ACT_ABORT, NULL }, /* segmentation violation */
120 #ifdef SIGSYS
121 { SIGSYS, ACT_ABORT, NULL }, /* bad argument to system call */
122 #endif
123 { SIGPIPE, ACT_HIDE, NULL }, /* write on a pipe with no one to read it */
124 { SIGALRM, ACT_EXIT, NULL }, /* alarm clock */
125 { SIGTERM, ACT_EXIT, NULL }, /* software termination signal from kill */
126 { SIGUSR1, ACT_SYSTEM, NULL }, /* user defined signal 1 */
127 { SIGUSR2, ACT_SYSTEM, NULL }, /* user defined signal 2 */
128 { SIGCHLD, ACT_SYSTEM, NULL }, /* child status change */
129 #ifdef SIGPWR
130 { SIGPWR, ACT_IGNORE, NULL }, /* power-fail restart */
131 #endif
132 { SIGWINCH, ACT_IGNORE, NULL }, /* window size change */
133 { SIGURG, ACT_EXIT, NULL }, /* urgent socket condition */
134 #ifdef SIGPOLL
135 { SIGPOLL, ACT_EXIT, NULL }, /* pollable event occured */
136 #endif
137 { SIGSTOP, ACT_SYSTEM, NULL }, /* stop (cannot be caught or ignored) */
138 { SIGTSTP, ACT_SYSTEM, NULL }, /* user stop requested from tty */
139 { SIGCONT, ACT_SYSTEM, NULL }, /* stopped process has been continued */
140 { SIGTTIN, ACT_SYSTEM, NULL }, /* background tty read attempted */
141 { SIGTTOU, ACT_SYSTEM, NULL }, /* background tty write attempted */
142 { SIGVTALRM, ACT_EXIT, NULL }, /* virtual timer expired */
143 { SIGPROF, ACT_SYSTEM, NULL }, /* profiling timer expired */
144 /*Change from ACT_EXIT to ACT_SYSTEM for SIGPROF is so that profiling signals do
145 not get taken by the new handler - the new handler does not pass on context
146 information which causes 'collect' to crash. This is a way of avoiding
147 what looks like a bug in the new handler*/
148 { SIGXCPU, ACT_ABORT, NULL }, /* exceeded cpu limit */
149 { SIGXFSZ, ACT_ABORT, NULL } /* exceeded file size limit */
151 const int NoSignals = sizeof(Signals) / sizeof(struct SignalAction);
153 static sal_Bool bErrorReportingEnabled = sal_True;
154 static sal_Bool bInitSignal = sal_False;
155 static oslMutex SignalListMutex;
156 static oslSignalHandlerImpl* SignalList;
157 static sal_Bool bDoHardKill = sal_False;
158 static sal_Bool bSetSEGVHandler = sal_False;
159 static sal_Bool bSetWINCHHandler = sal_False;
160 static sal_Bool bSetILLHandler = sal_False;
162 static void SignalHandlerFunction(int);
164 static void getExecutableName_Impl (rtl_String ** ppstrProgName)
166 rtl_uString * ustrProgFile = 0;
167 osl_getExecutableFile (&ustrProgFile);
168 if (ustrProgFile)
170 rtl_uString * ustrProgName = 0;
171 osl_systemPathGetFileNameOrLastDirectoryPart (ustrProgFile, &ustrProgName);
172 if (ustrProgName != 0)
174 rtl_uString2String (
175 ppstrProgName,
176 rtl_uString_getStr (ustrProgName), rtl_uString_getLength (ustrProgName),
177 osl_getThreadTextEncoding(),
178 OUSTRING_TO_OSTRING_CVTFLAGS);
179 rtl_uString_release (ustrProgName);
181 rtl_uString_release (ustrProgFile);
185 static sal_Bool is_soffice_Impl (void)
187 sal_Int32 idx = -1;
188 rtl_String * strProgName = 0;
190 getExecutableName_Impl (&strProgName);
191 if (strProgName)
193 idx = rtl_str_indexOfStr (rtl_string_getStr (strProgName), "soffice");
194 rtl_string_release (strProgName);
196 return (idx != -1);
199 static sal_Bool InitSignal()
201 int i;
202 struct sigaction act;
203 struct sigaction oact;
205 if (is_soffice_Impl())
207 sal_uInt32 argi;
208 sal_uInt32 argc;
209 rtl_uString *ustrCommandArg = 0;
211 argc = osl_getCommandArgCount();
212 for ( argi = 0; argi < argc; argi++ )
214 if (osl_Process_E_None == osl_getCommandArg (argi, &ustrCommandArg))
216 if (0 == rtl_ustr_ascii_compare (rtl_uString_getStr (ustrCommandArg), "-bean"))
218 bDoHardKill = sal_True;
219 break;
223 if (ustrCommandArg)
225 rtl_uString_release (ustrCommandArg);
226 ustrCommandArg = 0;
229 // WORKAROUND FOR SEGV HANDLER CONFLICT
231 // the java jit needs SIGSEGV for proper work
232 // and we need SIGSEGV for the office crashguard
234 // TEMPORARY SOLUTION:
235 // the office sets the signal handler during startup
236 // java can than overwrite it, if needed
237 bSetSEGVHandler = sal_True;
239 // WORKAROUND FOR WINCH HANDLER (SEE ABOVE)
240 bSetWINCHHandler = sal_True;
242 // WORKAROUND FOR ILLEGAL INSTRUCTION HANDLER (SEE ABOVE)
243 bSetILLHandler = sal_True;
246 SignalListMutex = osl_createMutex();
248 act.sa_handler = SignalHandlerFunction;
249 act.sa_flags = SA_RESTART;
251 sigfillset(&(act.sa_mask));
253 /* Initialize the rest of the signals */
254 for (i = 0; i < NoSignals; i++)
256 /* hack: stomcatd is attaching JavaVM wich dont work with an sigaction(SEGV) */
257 if ((bSetSEGVHandler || Signals[i].Signal != SIGSEGV)
258 && (bSetWINCHHandler || Signals[i].Signal != SIGWINCH)
259 && (bSetILLHandler || Signals[i].Signal != SIGILL))
261 if (Signals[i].Action != ACT_SYSTEM)
263 if (Signals[i].Action == ACT_HIDE)
265 struct sigaction ign;
267 ign.sa_handler = SIG_IGN;
268 ign.sa_flags = 0;
269 sigemptyset(&ign.sa_mask);
271 if (sigaction(Signals[i].Signal, &ign, &oact) == 0)
272 Signals[i].Handler = oact.sa_handler;
273 else
274 Signals[i].Handler = SIG_DFL;
276 else
277 if (sigaction(Signals[i].Signal, &act, &oact) == 0)
278 Signals[i].Handler = oact.sa_handler;
279 else
280 Signals[i].Handler = SIG_DFL;
285 return sal_True;
288 static sal_Bool DeInitSignal()
290 int i;
291 struct sigaction act;
293 act.sa_flags = 0;
294 sigemptyset(&(act.sa_mask));
296 /* Initialize the rest of the signals */
297 for (i = NoSignals - 1; i >= 0; i--)
298 if (Signals[i].Action != ACT_SYSTEM)
300 act.sa_handler = Signals[i].Handler;
302 sigaction(Signals[i].Signal, &act, NULL);
305 osl_destroyMutex(SignalListMutex);
307 return sal_False;
310 #if defined (SAL_ENABLE_CRASH_REPORT) && defined(INCLUDE_BACKTRACE)
312 /*****************************************************************************/
313 /* Generate MD5 checksum */
314 /*****************************************************************************/
316 static sal_uInt32 calc_md5_checksum( const char *filename, sal_uInt8 *pChecksum, sal_uInt32 nChecksumLen )
318 sal_uInt32 nBytesProcessed = 0;
320 FILE *fp = fopen( filename, "r" );
322 if ( fp )
324 rtlDigest digest = rtl_digest_createMD5();
326 if ( digest )
328 size_t nBytesRead;
329 sal_uInt8 buffer[4096];
330 rtlDigestError error = rtl_Digest_E_None;
332 while ( rtl_Digest_E_None == error &&
333 0 != (nBytesRead = fread( buffer, 1, sizeof(buffer), fp )) )
335 error = rtl_digest_updateMD5( digest, buffer, nBytesRead );
336 nBytesProcessed += nBytesRead;
339 if ( rtl_Digest_E_None == error )
341 error = rtl_digest_getMD5( digest, pChecksum, nChecksumLen );
344 if ( rtl_Digest_E_None != error )
345 nBytesProcessed = 0;
347 rtl_digest_destroyMD5( digest );
350 fclose( fp );
353 return nBytesProcessed;
356 /*****************************************************************************/
357 /* Call crash reporter */
358 /*****************************************************************************/
360 /* Helper function to encode and write a string to a stream */
362 static int fputs_xml( const char *string, FILE *stream )
364 int result = 0;
366 while ( result >= 0 && *string )
368 switch( *string )
370 case '&':
371 result = fputs( "&amp;", stream );
372 break;
373 case '<':
374 result = fputs( "&lt;", stream );
375 break;
376 case '>':
377 result = fputs( "&gt;", stream );
378 break;
379 default:
380 result = fputc( *string, stream );
381 break;
384 string++;
387 return result;
389 #endif
391 /* Create intermediate files and run crash reporter */
393 #define REPORTENV_PARAM "-crashreportenv:"
395 static int ReportCrash( int Signal )
397 #ifdef SAL_ENABLE_CRASH_REPORT
398 static sal_Bool bCrashReporterExecuted = sal_False;
399 sal_Bool bAutoCrashReport = sal_False;
401 sal_uInt32 argi;
402 sal_uInt32 argc;
403 rtl_uString *ustrCommandArg = NULL;
405 if ( !bErrorReportingEnabled )
406 return -1;
408 argc = osl_getCommandArgCount();
410 for ( argi = 0; argi < argc; argi++ )
412 if ( osl_Process_E_None == osl_getCommandArg( argi, &ustrCommandArg ) )
414 if ( 0 == rtl_ustr_ascii_compare( rtl_uString_getStr( ustrCommandArg ), "-nocrashreport" ) )
416 rtl_uString_release( ustrCommandArg );
417 return -1;
419 else if ( 0 == rtl_ustr_ascii_compare( rtl_uString_getStr( ustrCommandArg ), "-autocrashreport" ) )
421 bAutoCrashReport = sal_True;
423 else if ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength(
424 rtl_uString_getStr( ustrCommandArg ), rtl_uString_getLength( ustrCommandArg ),
425 REPORTENV_PARAM, strlen(REPORTENV_PARAM) )
428 rtl_uString *ustrEnvironment = NULL;
429 rtl_String *strEnv = NULL;
431 rtl_uString_newFromStr( &ustrEnvironment, rtl_uString_getStr( ustrCommandArg ) + strlen(REPORTENV_PARAM) );
433 if ( ustrEnvironment )
435 rtl_uString2String(
436 &strEnv,
437 rtl_uString_getStr( ustrEnvironment ), rtl_uString_getLength( ustrEnvironment ),
438 osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS
441 if ( strEnv )
443 putenv( rtl_string_getStr( strEnv ) );
444 rtl_string_release( strEnv );
447 rtl_uString_release( ustrEnvironment );
455 if ( ustrCommandArg )
456 rtl_uString_release( ustrCommandArg );
458 if ( !bCrashReporterExecuted )
460 int i;
461 /* struct sigaction act; */
463 for (i = 0; i < NoSignals; i++)
465 if (Signals[i].Signal == Signal && Signals[i].Action == ACT_ABORT )
467 int ret;
468 char szShellCmd[512];
469 char *pXMLTempName = NULL;
470 char *pStackTempName = NULL;
471 char *pChecksumTempName = NULL;
473 #ifdef INCLUDE_BACKTRACE
474 char szXMLTempNameBuffer[L_tmpnam];
475 char szChecksumTempNameBuffer[L_tmpnam];
476 char szStackTempNameBuffer[L_tmpnam];
478 void *stackframes[MAX_STACK_FRAMES];
479 int iFrame;
480 int nFrames = backtrace( stackframes, sizeof(stackframes)/sizeof(stackframes[0]));
482 FILE *xmlout = NULL, *stackout = NULL, *checksumout = NULL;
483 int fdxml, fdstk, fdchksum;
485 strncpy( szXMLTempNameBuffer, P_tmpdir, sizeof(szXMLTempNameBuffer) );
486 strncat( szXMLTempNameBuffer, "/crxmlXXXXXX", sizeof(szXMLTempNameBuffer) );
488 strncpy( szStackTempNameBuffer, P_tmpdir, sizeof(szStackTempNameBuffer) );
489 strncat( szStackTempNameBuffer, "/crstkXXXXXX", sizeof(szStackTempNameBuffer) );
491 strncpy( szChecksumTempNameBuffer, P_tmpdir, sizeof(szChecksumTempNameBuffer) );
492 strncat( szChecksumTempNameBuffer, "/crchkXXXXXX", sizeof(szChecksumTempNameBuffer) );
494 fdxml = mkstemp(szXMLTempNameBuffer);
495 fdstk = mkstemp(szStackTempNameBuffer);
496 fdchksum = mkstemp(szChecksumTempNameBuffer);
498 xmlout = fdopen( fdxml , "w" );
499 stackout = fdopen( fdstk , "w" );
500 checksumout = fdopen( fdchksum, "w" );
502 pXMLTempName = szXMLTempNameBuffer;
503 pStackTempName = szStackTempNameBuffer;
504 pChecksumTempName = szChecksumTempNameBuffer;
507 if ( xmlout && stackout && checksumout )
509 fprintf( xmlout, "<errormail:Stack type=\"%s\">\n", STACKTYPE );
511 fprintf( checksumout, "<errormail:Checksums type=\"MD5\">\n" );
513 for ( iFrame = 0; iFrame < nFrames; iFrame++ )
515 Dl_info dl_info;
517 fprintf( stackout, "0x%" SAL_PRIxUINTPTR ":",
518 SAL_INT_CAST(sal_uIntPtr, stackframes[iFrame]) );
520 fprintf( xmlout, "<errormail:StackInfo pos=\"%d\" ip=\"0x%" SAL_PRIxUINTPTR "\"",
521 iFrame,
522 SAL_INT_CAST(sal_uIntPtr, stackframes[iFrame])
525 memset( &dl_info, 0, sizeof(dl_info) );
527 /* dladdr may fail */
528 if ( dladdr( stackframes[iFrame], &dl_info) )
530 const char *dli_fname = NULL;
531 char *dli_fdir = NULL;
532 char szDirectory[PATH_MAX];
533 char szCanonicDirectory[PATH_MAX];
535 /* Don't expect that dladdr filled all members of dl_info */
537 dli_fname = dl_info.dli_fname ? strrchr( dl_info.dli_fname, '/' ) : NULL;
538 if ( dli_fname )
540 ++dli_fname;
541 memcpy( szDirectory, dl_info.dli_fname, dli_fname - dl_info.dli_fname );
542 szDirectory[dli_fname - dl_info.dli_fname] = 0;
544 dli_fdir = realpath( szDirectory, szCanonicDirectory ) ? szCanonicDirectory : szDirectory;
546 if ( *dli_fdir && dli_fdir[ strlen(dli_fdir) - 1 ] != '/' )
547 strcat( dli_fdir, "/" );
549 else
550 dli_fname = dl_info.dli_fname;
552 /* create checksum of library on stack */
553 if ( dli_fname )
555 sal_uInt8 checksum[RTL_DIGEST_LENGTH_MD5];
557 sal_uInt32 nBytesProcessed = calc_md5_checksum(
558 dl_info.dli_fname, checksum, sizeof(checksum) );
559 if ( nBytesProcessed )
561 int j;
563 fprintf( checksumout, "<errormail:Checksum sum=\"0x" );
564 for ( j = 0; j < 16; fprintf( checksumout, "%02X", checksum[j++] ) );
565 fprintf( checksumout,
566 "\" bytes=\"%lu\" file=\"%s\"/>\n",
567 SAL_INT_CAST(
568 unsigned long, nBytesProcessed),
569 dli_fname );
573 if ( dl_info.dli_fbase && dl_info.dli_fname )
575 fprintf( stackout, " %s + 0x%" SAL_PRI_PTRDIFFT "x",
576 dl_info.dli_fname,
577 (char*)stackframes[iFrame] - (char*)dl_info.dli_fbase
580 fprintf( xmlout, " rel=\"0x%" SAL_PRI_PTRDIFFT "x\"", (char *)stackframes[iFrame] - (char *)dl_info.dli_fbase );
581 if ( dli_fname )
582 fprintf( xmlout, " name=\"%s\"", dli_fname );
584 if ( dli_fdir )
585 fprintf( xmlout, " path=\"%s\"", dli_fdir );
587 else
588 fprintf( stackout, " ????????" );
590 if ( dl_info.dli_sname && dl_info.dli_saddr )
592 fputs( " (", stackout );
593 fputs_xml( dl_info.dli_sname, stackout );
594 fprintf( stackout, " + 0x%" SAL_PRI_PTRDIFFT "x)",
595 (char*)stackframes[iFrame] - (char*)dl_info.dli_saddr );
597 fputs( " ordinal=\"", xmlout );
598 fputs_xml( dl_info.dli_sname, xmlout );
599 fprintf( xmlout, "+0x%" SAL_PRI_PTRDIFFT "x\"",
600 (char *)stackframes[iFrame] - (char *)dl_info.dli_saddr );
604 else /* dladdr failed */
606 fprintf( stackout, " ????????" );
609 fprintf( stackout, "\n" );
610 fprintf( xmlout, "/>\n" );
614 fprintf( xmlout, "</errormail:Stack>\n" );
615 fprintf( checksumout, "</errormail:Checksums>\n" );
617 else
619 pXMLTempName = NULL;
620 pStackTempName = NULL;
621 pChecksumTempName = NULL;
624 if ( stackout )
625 fclose( stackout );
626 if ( xmlout )
627 fclose( xmlout );
628 if ( checksumout )
629 fclose( checksumout );
631 #if defined( LINUX )
632 if ( pXMLTempName && pChecksumTempName && pStackTempName )
633 snprintf( szShellCmd, sizeof(szShellCmd)/sizeof(szShellCmd[0]),
634 "crash_report -p %d -s %d -xml %s -chksum %s -stack %s%s",
635 getpid(),
636 Signal,
637 pXMLTempName,
638 pChecksumTempName,
639 pStackTempName,
640 bAutoCrashReport ? " -noui -send" : " -noui" );
641 #elif defined( MACOSX )
642 if ( pXMLTempName && pChecksumTempName && pStackTempName )
644 rtl_uString *crashrep_url = NULL;
645 rtl_uString *crashrep_path = NULL;
646 rtl_String *crashrep_path_system = NULL;
648 rtl_string2UString( &crashrep_url, RTL_CONSTASCII_USTRINGPARAM("$BRAND_BASE_DIR/program/crash_report.bin"), OSTRING_TO_OUSTRING_CVTFLAGS );
649 rtl_bootstrap_expandMacros( &crashrep_url );
650 osl_getSystemPathFromFileURL( crashrep_url, &crashrep_path );
651 rtl_uString2String(
652 &crashrep_path_system,
653 rtl_uString_getStr( crashrep_path ),
654 rtl_uString_getLength( crashrep_path ),
655 osl_getThreadTextEncoding(),
656 RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR );
658 rtl_uString_release( crashrep_url );
659 rtl_uString_release( crashrep_path );
661 snprintf( szShellCmd, sizeof(szShellCmd)/sizeof(szShellCmd[0]),
662 "%s -p %d -s %d -xml %s -chksum %s -stack %s%s",
663 rtl_string_getStr( crashrep_path_system ),
664 getpid(),
665 Signal,
666 pXMLTempName,
667 pChecksumTempName,
668 pStackTempName,
669 bAutoCrashReport ? " -noui -send" : " -noui" );
671 rtl_string_release( crashrep_path_system );
673 printf( "%s\n", szShellCmd );
675 #elif defined ( SOLARIS )
676 if ( pXMLTempName && pChecksumTempName )
677 snprintf( szShellCmd, sizeof(szShellCmd)/sizeof(szShellCmd[0]),
678 "crash_report -p %d -s %d -xml %s -chksum %s%s",
679 getpid(),
680 Signal,
681 pXMLTempName,
682 pChecksumTempName,
683 bAutoCrashReport ? " -noui -send" : " -noui" );
684 #endif
686 #else /* defined INCLUDE BACKTRACE */
687 snprintf( szShellCmd, sizeof(szShellCmd)/sizeof(szShellCmd[0]),
688 "crash_report -p %d -s %d%s", getpid(), Signal, bAutoCrashReport ? " -noui -send" : " -noui" );
689 #endif /* defined INCLUDE BACKTRACE */
692 ret = system( szShellCmd );
694 if ( pXMLTempName )
695 unlink( pXMLTempName );
697 if ( pStackTempName )
698 unlink( pStackTempName );
700 if ( pChecksumTempName )
701 unlink( pChecksumTempName );
703 if ( -1 != ret )
705 bCrashReporterExecuted = sal_True;
706 return 1;
708 else
709 return -1;
714 return 0;
717 return 1;
718 #else /* defined SAL_ENABLE_CRASH_REPORT */
719 /* the utility crash_report is not build, so do the same as when
720 the option -nocrashreport is used */
721 (void) Signal; // avoid warnings
722 return -1;
723 #endif /* defined SAL_ENABLE_CRASH_REPORT */
726 static void PrintStack( int sig )
728 #if ! defined(MACOSX) || defined(INCLUDE_BACKTRACE)
729 void *buffer[MAX_STACK_FRAMES];
730 int size = backtrace( buffer, sizeof(buffer) / sizeof(buffer[0]) );
731 #endif
733 fprintf( stderr, "\n\nFatal exception: Signal %d\n", sig );
735 #if defined(MACOSX) && ! defined(INCLUDE_BACKTRACE)
736 fprintf( stderr, "Please turn on Enable Crash Reporting and\nAutomatic Display of Crashlogs in the Console application\n" );
737 #else
738 if ( size > 0 )
740 fputs( "Stack:\n", stderr );
741 backtrace_symbols_fd( buffer, size, fileno(stderr) );
743 #endif
746 static oslSignalAction CallSignalHandler(oslSignalInfo *pInfo)
748 oslSignalHandlerImpl* pHandler = SignalList;
749 oslSignalAction Action = osl_Signal_ActCallNextHdl;
751 while (pHandler != NULL)
753 if ((Action = pHandler->Handler(pHandler->pData, pInfo))
754 != osl_Signal_ActCallNextHdl)
755 break;
757 pHandler = pHandler->pNext;
760 return Action;
763 void CallSystemHandler(int Signal)
765 int i;
766 struct sigaction act;
768 for (i = 0; i < NoSignals; i++)
770 if (Signals[i].Signal == Signal)
771 break;
774 if (i < NoSignals)
776 if ((Signals[i].Handler == NULL) ||
777 (Signals[i].Handler == SIG_DFL) ||
778 (Signals[i].Handler == SIG_IGN) ||
779 (Signals[i].Handler == SIG_ERR))
781 switch (Signals[i].Action)
783 case ACT_EXIT: /* terminate */
784 /* prevent dumping core on exit() */
785 _exit(255);
786 break;
788 case ACT_ABORT: /* terminate witch core dump */
789 ReportCrash( Signal );
790 act.sa_handler = SIG_DFL;
791 act.sa_flags = 0;
792 sigemptyset(&(act.sa_mask));
793 sigaction(SIGABRT, &act, NULL);
794 PrintStack( Signal );
795 abort();
796 break;
798 case ACT_IGNORE: /* ignore */
799 break;
801 default: /* should never happen */
802 OSL_ASSERT(0);
805 else
806 (*Signals[i].Handler)(Signal);
811 /*****************************************************************************/
812 /* SignalHandlerFunction */
813 /*****************************************************************************/
814 void SignalHandlerFunction(int Signal)
816 oslSignalInfo Info;
817 struct sigaction act;
819 Info.UserSignal = Signal;
820 Info.UserData = NULL;
822 switch (Signal)
824 case SIGBUS:
825 case SIGILL:
826 case SIGSEGV:
827 case SIGIOT:
828 #if ( SIGIOT != SIGABRT )
829 case SIGABRT:
830 #endif
831 Info.Signal = osl_Signal_AccessViolation;
832 break;
834 case -1:
835 Info.Signal = osl_Signal_IntegerDivideByZero;
836 break;
838 case SIGFPE:
839 Info.Signal = osl_Signal_FloatDivideByZero;
840 break;
842 case SIGINT:
843 case SIGTERM:
844 case SIGQUIT:
845 case SIGHUP:
846 Info.Signal = osl_Signal_Terminate;
847 break;
849 default:
850 Info.Signal = osl_Signal_System;
851 break;
854 ReportCrash( Signal );
856 /* Portal Demo HACK !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
857 if (bDoHardKill && (Info.Signal == osl_Signal_AccessViolation))
858 _exit(255);
859 /* Portal Demo HACK !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
862 switch (CallSignalHandler(&Info))
864 case osl_Signal_ActCallNextHdl:
865 CallSystemHandler(Signal);
866 break;
868 case osl_Signal_ActAbortApp:
869 ReportCrash( Signal );
870 act.sa_handler = SIG_DFL;
871 act.sa_flags = 0;
872 sigemptyset(&(act.sa_mask));
873 sigaction(SIGABRT, &act, NULL);
874 PrintStack( Signal );
875 abort();
876 break;
878 case osl_Signal_ActKillApp:
879 /* prevent dumping core on exit() */
880 _exit(255);
881 break;
882 default:
883 break;
887 /*****************************************************************************/
888 /* osl_addSignalHandler */
889 /*****************************************************************************/
890 oslSignalHandler SAL_CALL osl_addSignalHandler(oslSignalHandlerFunction Handler, void* pData)
892 oslSignalHandlerImpl* pHandler;
894 OSL_ASSERT(Handler != NULL);
895 if ( Handler == 0 )
897 return 0;
900 if (! bInitSignal)
901 bInitSignal = InitSignal();
903 pHandler = (oslSignalHandlerImpl*) calloc(1, sizeof(oslSignalHandlerImpl));
905 if (pHandler != NULL)
907 pHandler->Handler = Handler;
908 pHandler->pData = pData;
910 osl_acquireMutex(SignalListMutex);
912 pHandler->pNext = SignalList;
913 SignalList = pHandler;
915 osl_releaseMutex(SignalListMutex);
917 return (pHandler);
920 return (NULL);
923 /*****************************************************************************/
924 /* osl_removeSignalHandler */
925 /*****************************************************************************/
926 sal_Bool SAL_CALL osl_removeSignalHandler(oslSignalHandler Handler)
928 oslSignalHandlerImpl *pHandler, *pPrevious = NULL;
930 OSL_ASSERT(Handler != NULL);
932 if (! bInitSignal)
933 bInitSignal = InitSignal();
935 osl_acquireMutex(SignalListMutex);
937 pHandler = SignalList;
939 while (pHandler != NULL)
941 if (pHandler == Handler)
943 if (pPrevious)
944 pPrevious->pNext = pHandler->pNext;
945 else
946 SignalList = pHandler->pNext;
948 osl_releaseMutex(SignalListMutex);
950 if (SignalList == NULL)
951 bInitSignal = DeInitSignal();
953 free(pHandler);
955 return (sal_True);
958 pPrevious = pHandler;
959 pHandler = pHandler->pNext;
962 osl_releaseMutex(SignalListMutex);
964 return (sal_False);
967 /*****************************************************************************/
968 /* osl_raiseSignal */
969 /*****************************************************************************/
970 oslSignalAction SAL_CALL osl_raiseSignal(sal_Int32 UserSignal, void* UserData)
972 oslSignalInfo Info;
973 oslSignalAction Action;
975 if (! bInitSignal)
976 bInitSignal = InitSignal();
978 osl_acquireMutex(SignalListMutex);
980 Info.Signal = osl_Signal_User;
981 Info.UserSignal = UserSignal;
982 Info.UserData = UserData;
984 Action = CallSignalHandler(&Info);
986 osl_releaseMutex(SignalListMutex);
988 return (Action);
991 /*****************************************************************************/
992 /* osl_setErrorReporting */
993 /*****************************************************************************/
994 sal_Bool SAL_CALL osl_setErrorReporting( sal_Bool bEnable )
996 sal_Bool bOld = bErrorReportingEnabled;
997 bErrorReportingEnabled = bEnable;
999 return bOld;