1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
32 #define MAX_STACK_FRAMES 256
37 #include "backtrace.h"
38 #define INCLUDE_BACKTRACE
39 #define STACKTYPE "MacOsX_X86"
47 #define INCLUDE_BACKTRACE
48 #define STACKTYPE "Linux"
53 #include "backtrace.h"
54 #define INCLUDE_BACKTRACE
57 #define STACKTYPE "Solaris_Sparc"
58 #elif defined( INTEL )
59 #define STACKTYPE "Solaris_X86"
61 #define STACKTYPE "Solaris_Unknown"
64 #endif /* defined SOLARIS */
66 #include <osl/diagnose.h>
67 #include <osl/mutex.h>
68 #include <osl/signal.h>
69 #include <osl/process.h>
70 #include <osl/thread.h>
71 #include <rtl/bootstrap.h>
72 #include <rtl/digest.h>
74 #include "file_path_helper.h"
80 #ifdef SAL_ENABLE_CRASH_REPORT
83 # define ACT_ABORT ACT_SYSTEM
86 #define MAX_PATH_LEN 2048
88 typedef struct _oslSignalHandlerImpl
90 oslSignalHandlerFunction Handler
;
92 struct _oslSignalHandlerImpl
* pNext
;
93 } oslSignalHandlerImpl
;
95 static struct SignalAction
102 { SIGHUP
, ACT_IGNORE
, NULL
}, /* hangup */
103 { SIGINT
, ACT_EXIT
, NULL
}, /* interrupt (rubout) */
104 { SIGQUIT
, ACT_EXIT
, NULL
}, /* quit (ASCII FS) */
105 { SIGILL
, ACT_SYSTEM
, NULL
}, /* illegal instruction (not reset when caught) */
106 /* changed from ACT_ABOUT to ACT_SYSTEM to try and get collector to run*/
107 { SIGTRAP
, ACT_ABORT
, NULL
}, /* trace trap (not reset when caught) */
108 #if ( SIGIOT != SIGABRT )
109 { SIGIOT
, ACT_ABORT
, NULL
}, /* IOT instruction */
111 { SIGABRT
, ACT_ABORT
, NULL
}, /* used by abort, replace SIGIOT in the future */
113 { SIGEMT
, ACT_SYSTEM
, NULL
}, /* EMT instruction */
114 /* changed from ACT_ABORT to ACT_SYSTEM to remove handler*/
115 /* SIGEMT may also be used by the profiler - so it is probably not a good
116 plan to have the new handler use this signal*/
118 { SIGFPE
, ACT_ABORT
, NULL
}, /* floating point exception */
119 { SIGKILL
, ACT_SYSTEM
, NULL
}, /* kill (cannot be caught or ignored) */
120 { SIGBUS
, ACT_ABORT
, NULL
}, /* bus error */
121 { SIGSEGV
, ACT_ABORT
, NULL
}, /* segmentation violation */
123 { SIGSYS
, ACT_ABORT
, NULL
}, /* bad argument to system call */
125 { SIGPIPE
, ACT_HIDE
, NULL
}, /* write on a pipe with no one to read it */
126 { SIGALRM
, ACT_EXIT
, NULL
}, /* alarm clock */
127 { SIGTERM
, ACT_EXIT
, NULL
}, /* software termination signal from kill */
128 { SIGUSR1
, ACT_SYSTEM
, NULL
}, /* user defined signal 1 */
129 { SIGUSR2
, ACT_SYSTEM
, NULL
}, /* user defined signal 2 */
130 { SIGCHLD
, ACT_SYSTEM
, NULL
}, /* child status change */
132 { SIGPWR
, ACT_IGNORE
, NULL
}, /* power-fail restart */
134 { SIGWINCH
, ACT_IGNORE
, NULL
}, /* window size change */
135 { SIGURG
, ACT_EXIT
, NULL
}, /* urgent socket condition */
137 { SIGPOLL
, ACT_EXIT
, NULL
}, /* pollable event occured */
139 { SIGSTOP
, ACT_SYSTEM
, NULL
}, /* stop (cannot be caught or ignored) */
140 { SIGTSTP
, ACT_SYSTEM
, NULL
}, /* user stop requested from tty */
141 { SIGCONT
, ACT_SYSTEM
, NULL
}, /* stopped process has been continued */
142 { SIGTTIN
, ACT_SYSTEM
, NULL
}, /* background tty read attempted */
143 { SIGTTOU
, ACT_SYSTEM
, NULL
}, /* background tty write attempted */
144 { SIGVTALRM
, ACT_EXIT
, NULL
}, /* virtual timer expired */
145 { SIGPROF
, ACT_SYSTEM
, NULL
}, /* profiling timer expired */
146 /*Change from ACT_EXIT to ACT_SYSTEM for SIGPROF is so that profiling signals do
147 not get taken by the new handler - the new handler does not pass on context
148 information which causes 'collect' to crash. This is a way of avoiding
149 what looks like a bug in the new handler*/
150 { SIGXCPU
, ACT_ABORT
, NULL
}, /* exceeded cpu limit */
151 { SIGXFSZ
, ACT_ABORT
, NULL
} /* exceeded file size limit */
153 const int NoSignals
= sizeof(Signals
) / sizeof(struct SignalAction
);
155 static sal_Bool bErrorReportingEnabled
= sal_True
;
156 static sal_Bool bInitSignal
= sal_False
;
157 static oslMutex SignalListMutex
;
158 static oslSignalHandlerImpl
* SignalList
;
159 static sal_Bool bDoHardKill
= sal_False
;
160 static sal_Bool bSetSEGVHandler
= sal_False
;
161 static sal_Bool bSetWINCHHandler
= sal_False
;
162 static sal_Bool bSetILLHandler
= sal_False
;
164 static void SignalHandlerFunction(int);
166 static void getExecutableName_Impl (rtl_String
** ppstrProgName
)
168 rtl_uString
* ustrProgFile
= 0;
169 osl_getExecutableFile (&ustrProgFile
);
172 rtl_uString
* ustrProgName
= 0;
173 osl_systemPathGetFileNameOrLastDirectoryPart (ustrProgFile
, &ustrProgName
);
174 if (ustrProgName
!= 0)
178 rtl_uString_getStr (ustrProgName
), rtl_uString_getLength (ustrProgName
),
179 osl_getThreadTextEncoding(),
180 OUSTRING_TO_OSTRING_CVTFLAGS
);
181 rtl_uString_release (ustrProgName
);
183 rtl_uString_release (ustrProgFile
);
187 static sal_Bool
is_soffice_Impl (void)
190 rtl_String
* strProgName
= 0;
192 getExecutableName_Impl (&strProgName
);
195 idx
= rtl_str_indexOfStr (rtl_string_getStr (strProgName
), "soffice");
196 rtl_string_release (strProgName
);
201 static sal_Bool
InitSignal()
204 struct sigaction act
;
205 struct sigaction oact
;
208 if (is_soffice_Impl())
212 rtl_uString
*ustrCommandArg
= 0;
214 argc
= osl_getCommandArgCount();
215 for ( argi
= 0; argi
< argc
; argi
++ )
217 if (osl_Process_E_None
== osl_getCommandArg (argi
, &ustrCommandArg
))
219 if (0 == rtl_ustr_ascii_compare (rtl_uString_getStr (ustrCommandArg
), "-bean"))
221 bDoHardKill
= sal_True
;
228 rtl_uString_release (ustrCommandArg
);
232 // WORKAROUND FOR SEGV HANDLER CONFLICT
234 // the java jit needs SIGSEGV for proper work
235 // and we need SIGSEGV for the office crashguard
237 // TEMPORARY SOLUTION:
238 // the office sets the signal handler during startup
239 // java can than overwrite it, if needed
240 bSetSEGVHandler
= sal_True
;
242 // WORKAROUND FOR WINCH HANDLER (SEE ABOVE)
243 bSetWINCHHandler
= sal_True
;
245 // WORKAROUND FOR ILLEGAL INSTRUCTION HANDLER (SEE ABOVE)
246 bSetILLHandler
= sal_True
;
249 SignalListMutex
= osl_createMutex();
251 act
.sa_handler
= SignalHandlerFunction
;
252 act
.sa_flags
= SA_RESTART
;
254 sigfillset(&(act
.sa_mask
));
256 /* Initialize the rest of the signals */
257 for (i
= 0; i
< NoSignals
; i
++)
259 /* hack: stomcatd is attaching JavaVM wich dont work with an sigaction(SEGV) */
260 if ((bSetSEGVHandler
|| Signals
[i
].Signal
!= SIGSEGV
)
261 && (bSetWINCHHandler
|| Signals
[i
].Signal
!= SIGWINCH
)
262 && (bSetILLHandler
|| Signals
[i
].Signal
!= SIGILL
))
264 if (Signals
[i
].Action
!= ACT_SYSTEM
)
266 if (Signals
[i
].Action
== ACT_HIDE
)
268 struct sigaction ign
;
270 ign
.sa_handler
= SIG_IGN
;
272 sigemptyset(&ign
.sa_mask
);
274 if (sigaction(Signals
[i
].Signal
, &ign
, &oact
) == 0)
275 Signals
[i
].Handler
= oact
.sa_handler
;
277 Signals
[i
].Handler
= SIG_DFL
;
280 if (sigaction(Signals
[i
].Signal
, &act
, &oact
) == 0)
281 Signals
[i
].Handler
= oact
.sa_handler
;
283 Signals
[i
].Handler
= SIG_DFL
;
288 /* Clear signal mask inherited from parent process (on Mac OS X, upon a
289 crash soffice re-execs itself from within the signal handler, so the
290 second soffice would have the guilty signal blocked and would freeze upon
291 encountering a similar crash again): */
292 if (sigemptyset(&unset
) < 0 ||
293 pthread_sigmask(SIG_SETMASK
, &unset
, NULL
) < 0)
295 OSL_TRACE("sigemptyset or pthread_sigmask failed");
301 static sal_Bool
DeInitSignal()
304 struct sigaction act
;
307 sigemptyset(&(act
.sa_mask
));
309 /* Initialize the rest of the signals */
310 for (i
= NoSignals
- 1; i
>= 0; i
--)
311 if (Signals
[i
].Action
!= ACT_SYSTEM
)
313 act
.sa_handler
= Signals
[i
].Handler
;
315 sigaction(Signals
[i
].Signal
, &act
, NULL
);
318 osl_destroyMutex(SignalListMutex
);
323 #if defined (SAL_ENABLE_CRASH_REPORT) && defined(INCLUDE_BACKTRACE)
325 /*****************************************************************************/
326 /* Generate MD5 checksum */
327 /*****************************************************************************/
329 static sal_uInt32
calc_md5_checksum( const char *filename
, sal_uInt8
*pChecksum
, sal_uInt32 nChecksumLen
)
331 sal_uInt32 nBytesProcessed
= 0;
333 FILE *fp
= fopen( filename
, "r" );
337 rtlDigest digest
= rtl_digest_createMD5();
342 sal_uInt8 buffer
[4096];
343 rtlDigestError error
= rtl_Digest_E_None
;
345 while ( rtl_Digest_E_None
== error
&&
346 0 != (nBytesRead
= fread( buffer
, 1, sizeof(buffer
), fp
)) )
348 error
= rtl_digest_updateMD5( digest
, buffer
, nBytesRead
);
349 nBytesProcessed
+= nBytesRead
;
352 if ( rtl_Digest_E_None
== error
)
354 error
= rtl_digest_getMD5( digest
, pChecksum
, nChecksumLen
);
357 if ( rtl_Digest_E_None
!= error
)
360 rtl_digest_destroyMD5( digest
);
366 return nBytesProcessed
;
369 /*****************************************************************************/
370 /* Call crash reporter */
371 /*****************************************************************************/
373 /* Helper function to encode and write a string to a stream */
375 static int fputs_xml( const char *string
, FILE *stream
)
379 while ( result
>= 0 && *string
)
384 result
= fputs( "&", stream
);
387 result
= fputs( "<", stream
);
390 result
= fputs( ">", stream
);
393 result
= fputc( *string
, stream
);
404 /* Create intermediate files and run crash reporter */
406 #define REPORTENV_PARAM "-crashreportenv:"
408 #if defined SAL_ENABLE_CRASH_REPORT && defined INCLUDE_BACKTRACE && \
418 callback(struct dl_phdr_info
*info
, size_t size
, void *data
)
420 const ElfW(Phdr
) *pDynamic
= NULL
;
422 if (size
== sizeof(struct dl_phdr_info
))
425 for (i
= 0; i
< info
->dlpi_phnum
; ++i
)
427 if (info
->dlpi_phdr
[i
].p_type
== PT_DYNAMIC
)
429 pDynamic
= &(info
->dlpi_phdr
[i
]);
440 const char *dsoname
= info
->dlpi_name
;
442 dynamic_entry
* entry
= (dynamic_entry
*)data
;
444 if (strcmp(dsoname
, "") == 0)
446 snprintf(buffer
, sizeof(buffer
), "/proc/%d/exe", getpid());
447 if ((len
= readlink(buffer
, exe
, PATH_MAX
)) != -1)
454 if (strcmp(dsoname
, entry
->name
) == 0)
456 entry
->offset
= pDynamic
->p_offset
;
463 /* Get the location of the .dynamic section offset for the given elf file.
464 * i.e. same as the "Offset" value shown for DYNAMIC from readelf -l foo
466 * We want to know this value so that if the binaries have been modifed
467 * by prelink then we can still process the call stack on server side
468 * by comparing this value to that of an "un-prelinked but known to be
469 * otherwise equivalent" version of those binaries and adjust the call
470 * stack addresses by the differences between .dynamic addresses so as
471 * to be able to map the prelinked addresses back to the unprelinked
477 dynamic_section_offset(const char *name
)
484 dl_iterate_phdr(callback
, &entry
);
490 static int ReportCrash( int Signal
)
492 #ifdef SAL_ENABLE_CRASH_REPORT
493 static sal_Bool bCrashReporterExecuted
= sal_False
;
494 sal_Bool bAutoCrashReport
= sal_False
;
498 rtl_uString
*ustrCommandArg
= NULL
;
500 if ( !bErrorReportingEnabled
)
503 argc
= osl_getCommandArgCount();
505 for ( argi
= 0; argi
< argc
; argi
++ )
507 if ( osl_Process_E_None
== osl_getCommandArg( argi
, &ustrCommandArg
) )
509 if ( 0 == rtl_ustr_ascii_compare( rtl_uString_getStr( ustrCommandArg
), "-nocrashreport" ) )
511 rtl_uString_release( ustrCommandArg
);
514 else if ( 0 == rtl_ustr_ascii_compare( rtl_uString_getStr( ustrCommandArg
), "-autocrashreport" ) )
516 bAutoCrashReport
= sal_True
;
518 else if ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength(
519 rtl_uString_getStr( ustrCommandArg
), rtl_uString_getLength( ustrCommandArg
),
520 REPORTENV_PARAM
, strlen(REPORTENV_PARAM
) )
523 rtl_uString
*ustrEnvironment
= NULL
;
524 rtl_String
*strEnv
= NULL
;
526 rtl_uString_newFromStr( &ustrEnvironment
, rtl_uString_getStr( ustrCommandArg
) + strlen(REPORTENV_PARAM
) );
528 if ( ustrEnvironment
)
532 rtl_uString_getStr( ustrEnvironment
), rtl_uString_getLength( ustrEnvironment
),
533 osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS
538 putenv( rtl_string_getStr( strEnv
) );
539 rtl_string_release( strEnv
);
542 rtl_uString_release( ustrEnvironment
);
550 if ( ustrCommandArg
)
551 rtl_uString_release( ustrCommandArg
);
553 if ( !bCrashReporterExecuted
)
556 /* struct sigaction act; */
558 for (i
= 0; i
< NoSignals
; i
++)
560 if (Signals
[i
].Signal
== Signal
&& Signals
[i
].Action
== ACT_ABORT
)
563 char szShellCmd
[512] = { '\0' };
564 char *pXMLTempName
= NULL
;
565 char *pStackTempName
= NULL
;
566 char *pChecksumTempName
= NULL
;
568 #ifdef INCLUDE_BACKTRACE
569 char szXMLTempNameBuffer
[L_tmpnam
];
570 char szChecksumTempNameBuffer
[L_tmpnam
];
571 char szStackTempNameBuffer
[L_tmpnam
];
573 void *stackframes
[MAX_STACK_FRAMES
];
575 int nFrames
= backtrace( stackframes
, sizeof(stackframes
)/sizeof(stackframes
[0]));
577 FILE *xmlout
= NULL
, *stackout
= NULL
, *checksumout
= NULL
;
578 int fdxml
, fdstk
, fdchksum
;
580 strncpy( szXMLTempNameBuffer
, P_tmpdir
, sizeof(szXMLTempNameBuffer
) );
581 strncat( szXMLTempNameBuffer
, "/crxmlXXXXXX", sizeof(szXMLTempNameBuffer
) );
583 strncpy( szStackTempNameBuffer
, P_tmpdir
, sizeof(szStackTempNameBuffer
) );
584 strncat( szStackTempNameBuffer
, "/crstkXXXXXX", sizeof(szStackTempNameBuffer
) );
586 strncpy( szChecksumTempNameBuffer
, P_tmpdir
, sizeof(szChecksumTempNameBuffer
) );
587 strncat( szChecksumTempNameBuffer
, "/crchkXXXXXX", sizeof(szChecksumTempNameBuffer
) );
589 fdxml
= mkstemp(szXMLTempNameBuffer
);
590 fdstk
= mkstemp(szStackTempNameBuffer
);
591 fdchksum
= mkstemp(szChecksumTempNameBuffer
);
593 xmlout
= fdopen( fdxml
, "w" );
594 stackout
= fdopen( fdstk
, "w" );
595 checksumout
= fdopen( fdchksum
, "w" );
597 pXMLTempName
= szXMLTempNameBuffer
;
598 pStackTempName
= szStackTempNameBuffer
;
599 pChecksumTempName
= szChecksumTempNameBuffer
;
602 if ( xmlout
&& stackout
&& checksumout
)
604 fprintf( xmlout
, "<errormail:Stack type=\"%s\">\n", STACKTYPE
);
606 fprintf( checksumout
, "<errormail:Checksums type=\"MD5\">\n" );
608 for ( iFrame
= 0; iFrame
< nFrames
; iFrame
++ )
612 fprintf( stackout
, "0x%" SAL_PRIxUINTPTR
":",
613 SAL_INT_CAST(sal_uIntPtr
, stackframes
[iFrame
]) );
615 fprintf( xmlout
, "<errormail:StackInfo pos=\"%d\" ip=\"0x%" SAL_PRIxUINTPTR
"\"",
617 SAL_INT_CAST(sal_uIntPtr
, stackframes
[iFrame
])
620 memset( &dl_info
, 0, sizeof(dl_info
) );
622 /* dladdr may fail */
623 if ( dladdr( stackframes
[iFrame
], &dl_info
) )
625 const char *dli_fname
= NULL
;
626 char *dli_fdir
= NULL
;
627 char szDirectory
[PATH_MAX
];
628 char szCanonicDirectory
[PATH_MAX
];
630 /* Don't expect that dladdr filled all members of dl_info */
632 dli_fname
= dl_info
.dli_fname
? strrchr( dl_info
.dli_fname
, '/' ) : NULL
;
636 memcpy( szDirectory
, dl_info
.dli_fname
, dli_fname
- dl_info
.dli_fname
);
637 szDirectory
[dli_fname
- dl_info
.dli_fname
] = 0;
639 dli_fdir
= realpath( szDirectory
, szCanonicDirectory
) ? szCanonicDirectory
: szDirectory
;
641 if ( *dli_fdir
&& dli_fdir
[ strlen(dli_fdir
) - 1 ] != '/' )
642 strcat( dli_fdir
, "/" );
645 dli_fname
= dl_info
.dli_fname
;
647 /* create checksum of library on stack */
650 sal_uInt8 checksum
[RTL_DIGEST_LENGTH_MD5
];
652 sal_uInt32 nBytesProcessed
= calc_md5_checksum(
653 dl_info
.dli_fname
, checksum
, sizeof(checksum
) );
654 if ( nBytesProcessed
)
658 fprintf( checksumout
, "<errormail:Checksum sum=\"0x" );
659 for ( j
= 0; j
< 16; fprintf( checksumout
, "%02X", checksum
[j
++] ) );
660 fprintf( checksumout
,
661 "\" bytes=\"%lu\" file=\"%s\"/>\n",
663 unsigned long, nBytesProcessed
),
668 if ( dl_info
.dli_fbase
&& dl_info
.dli_fname
)
671 ElfW(Off
) dynamic_offset
= dynamic_section_offset(dl_info
.dli_fname
);
672 fprintf( stackout
, " 0x%" SAL_PRI_SIZET
"x:", dynamic_offset
);
675 fprintf( stackout
, " %s + 0x%" SAL_PRI_PTRDIFFT
"x",
677 (char*)stackframes
[iFrame
] - (char*)dl_info
.dli_fbase
680 fprintf( xmlout
, " rel=\"0x%" SAL_PRI_PTRDIFFT
"x\"", (char *)stackframes
[iFrame
] - (char *)dl_info
.dli_fbase
);
682 fprintf( xmlout
, " name=\"%s\"", dli_fname
);
685 fprintf( xmlout
, " path=\"%s\"", dli_fdir
);
688 fprintf( xmlout
, " dynamicoffset=\"0x%" SAL_PRI_SIZET
"x\"", dynamic_offset
);
692 fprintf( stackout
, " ????????" );
694 if ( dl_info
.dli_sname
&& dl_info
.dli_saddr
)
696 fputs( " (", stackout
);
697 fputs_xml( dl_info
.dli_sname
, stackout
);
698 fprintf( stackout
, " + 0x%" SAL_PRI_PTRDIFFT
"x)",
699 (char*)stackframes
[iFrame
] - (char*)dl_info
.dli_saddr
);
701 fputs( " ordinal=\"", xmlout
);
702 fputs_xml( dl_info
.dli_sname
, xmlout
);
703 fprintf( xmlout
, "+0x%" SAL_PRI_PTRDIFFT
"x\"",
704 (char *)stackframes
[iFrame
] - (char *)dl_info
.dli_saddr
);
708 else /* dladdr failed */
710 fprintf( stackout
, " ????????" );
713 fprintf( stackout
, "\n" );
714 fprintf( xmlout
, "/>\n" );
718 fprintf( xmlout
, "</errormail:Stack>\n" );
719 fprintf( checksumout
, "</errormail:Checksums>\n" );
724 pStackTempName
= NULL
;
725 pChecksumTempName
= NULL
;
733 fclose( checksumout
);
735 if ( pXMLTempName
&& pChecksumTempName
&& pStackTempName
)
736 #endif /* INCLUDE_BACKTRACE */
738 rtl_uString
* crashrep_url
= NULL
;
739 rtl_uString
* crashrep_path
= NULL
;
740 rtl_String
* crashrep_path_system
= NULL
;
743 RTL_CONSTASCII_USTRINGPARAM(
744 "$BRAND_BASE_DIR/program/crashrep"),
745 OSTRING_TO_OUSTRING_CVTFLAGS
);
746 rtl_bootstrap_expandMacros(&crashrep_url
);
747 osl_getSystemPathFromFileURL(crashrep_url
, &crashrep_path
);
749 &crashrep_path_system
,
750 rtl_uString_getStr(crashrep_path
),
751 rtl_uString_getLength(crashrep_path
),
752 osl_getThreadTextEncoding(),
753 (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
754 | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR
));
755 rtl_uString_release(crashrep_url
);
756 rtl_uString_release(crashrep_path
);
757 #if defined INCLUDE_BACKTRACE && (defined LINUX || defined MACOSX)
758 snprintf( szShellCmd
, sizeof(szShellCmd
)/sizeof(szShellCmd
[0]),
759 "%s -p %d -s %d -xml %s -chksum %s -stack %s -noui%s",
760 rtl_string_getStr(crashrep_path_system
),
766 bAutoCrashReport
? " -send" : "" );
767 #elif defined INCLUDE_BACKTRACE && defined SOLARIS
768 snprintf( szShellCmd
, sizeof(szShellCmd
)/sizeof(szShellCmd
[0]),
769 "%s -p %d -s %d -xml %s -chksum %s -noui%s",
770 rtl_string_getStr(crashrep_path_system
),
775 bAutoCrashReport
? " -send" : "" );
777 snprintf( szShellCmd
, sizeof(szShellCmd
)/sizeof(szShellCmd
[0]),
778 "%s -p %d -s %d -noui%s",
779 rtl_string_getStr(crashrep_path_system
),
780 getpid(), Signal
, bAutoCrashReport
? " -send" : "" );
782 rtl_string_release(crashrep_path_system
);
785 ret
= szShellCmd
[0] == '\0' ? -1 : system( szShellCmd
);
788 unlink( pXMLTempName
);
790 if ( pStackTempName
)
791 unlink( pStackTempName
);
793 if ( pChecksumTempName
)
794 unlink( pChecksumTempName
);
798 bCrashReporterExecuted
= sal_True
;
811 #else /* defined SAL_ENABLE_CRASH_REPORT */
812 /* the utility crash_report is not build, so do the same as when
813 the option -nocrashreport is used */
814 (void) Signal
; // avoid warnings
816 #endif /* defined SAL_ENABLE_CRASH_REPORT */
819 static void PrintStack( int sig
)
821 #if ! defined(MACOSX) || defined(INCLUDE_BACKTRACE)
822 void *buffer
[MAX_STACK_FRAMES
];
823 int size
= backtrace( buffer
, sizeof(buffer
) / sizeof(buffer
[0]) );
826 fprintf( stderr
, "\n\nFatal exception: Signal %d\n", sig
);
828 #if defined(MACOSX) && ! defined(INCLUDE_BACKTRACE)
829 fprintf( stderr
, "Please turn on Enable Crash Reporting and\nAutomatic Display of Crashlogs in the Console application\n" );
833 fputs( "Stack:\n", stderr
);
834 backtrace_symbols_fd( buffer
, size
, fileno(stderr
) );
839 static oslSignalAction
CallSignalHandler(oslSignalInfo
*pInfo
)
841 oslSignalHandlerImpl
* pHandler
= SignalList
;
842 oslSignalAction Action
= osl_Signal_ActCallNextHdl
;
844 while (pHandler
!= NULL
)
846 if ((Action
= pHandler
->Handler(pHandler
->pData
, pInfo
))
847 != osl_Signal_ActCallNextHdl
)
850 pHandler
= pHandler
->pNext
;
856 void CallSystemHandler(int Signal
)
859 struct sigaction act
;
861 for (i
= 0; i
< NoSignals
; i
++)
863 if (Signals
[i
].Signal
== Signal
)
869 if ((Signals
[i
].Handler
== NULL
) ||
870 (Signals
[i
].Handler
== SIG_DFL
) ||
871 (Signals
[i
].Handler
== SIG_IGN
) ||
872 (Signals
[i
].Handler
== SIG_ERR
))
874 switch (Signals
[i
].Action
)
876 case ACT_EXIT
: /* terminate */
877 /* prevent dumping core on exit() */
881 case ACT_ABORT
: /* terminate witch core dump */
882 ReportCrash( Signal
);
883 act
.sa_handler
= SIG_DFL
;
885 sigemptyset(&(act
.sa_mask
));
886 sigaction(SIGABRT
, &act
, NULL
);
887 PrintStack( Signal
);
891 case ACT_IGNORE
: /* ignore */
894 default: /* should never happen */
899 (*Signals
[i
].Handler
)(Signal
);
904 /*****************************************************************************/
905 /* SignalHandlerFunction */
906 /*****************************************************************************/
907 void SignalHandlerFunction(int Signal
)
910 struct sigaction act
;
912 Info
.UserSignal
= Signal
;
913 Info
.UserData
= NULL
;
921 #if ( SIGIOT != SIGABRT )
924 Info
.Signal
= osl_Signal_AccessViolation
;
928 Info
.Signal
= osl_Signal_IntegerDivideByZero
;
932 Info
.Signal
= osl_Signal_FloatDivideByZero
;
939 Info
.Signal
= osl_Signal_Terminate
;
943 Info
.Signal
= osl_Signal_System
;
947 ReportCrash( Signal
);
949 /* Portal Demo HACK !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
950 if (bDoHardKill
&& (Info
.Signal
== osl_Signal_AccessViolation
))
952 /* Portal Demo HACK !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
955 switch (CallSignalHandler(&Info
))
957 case osl_Signal_ActCallNextHdl
:
958 CallSystemHandler(Signal
);
961 case osl_Signal_ActAbortApp
:
962 ReportCrash( Signal
);
963 act
.sa_handler
= SIG_DFL
;
965 sigemptyset(&(act
.sa_mask
));
966 sigaction(SIGABRT
, &act
, NULL
);
967 PrintStack( Signal
);
971 case osl_Signal_ActKillApp
:
972 /* prevent dumping core on exit() */
980 /*****************************************************************************/
981 /* osl_addSignalHandler */
982 /*****************************************************************************/
983 oslSignalHandler SAL_CALL
osl_addSignalHandler(oslSignalHandlerFunction Handler
, void* pData
)
985 oslSignalHandlerImpl
* pHandler
;
987 OSL_ASSERT(Handler
!= NULL
);
994 bInitSignal
= InitSignal();
996 pHandler
= (oslSignalHandlerImpl
*) calloc(1, sizeof(oslSignalHandlerImpl
));
998 if (pHandler
!= NULL
)
1000 pHandler
->Handler
= Handler
;
1001 pHandler
->pData
= pData
;
1003 osl_acquireMutex(SignalListMutex
);
1005 pHandler
->pNext
= SignalList
;
1006 SignalList
= pHandler
;
1008 osl_releaseMutex(SignalListMutex
);
1016 /*****************************************************************************/
1017 /* osl_removeSignalHandler */
1018 /*****************************************************************************/
1019 sal_Bool SAL_CALL
osl_removeSignalHandler(oslSignalHandler Handler
)
1021 oslSignalHandlerImpl
*pHandler
, *pPrevious
= NULL
;
1023 OSL_ASSERT(Handler
!= NULL
);
1026 bInitSignal
= InitSignal();
1028 osl_acquireMutex(SignalListMutex
);
1030 pHandler
= SignalList
;
1032 while (pHandler
!= NULL
)
1034 if (pHandler
== Handler
)
1037 pPrevious
->pNext
= pHandler
->pNext
;
1039 SignalList
= pHandler
->pNext
;
1041 osl_releaseMutex(SignalListMutex
);
1043 if (SignalList
== NULL
)
1044 bInitSignal
= DeInitSignal();
1051 pPrevious
= pHandler
;
1052 pHandler
= pHandler
->pNext
;
1055 osl_releaseMutex(SignalListMutex
);
1060 /*****************************************************************************/
1061 /* osl_raiseSignal */
1062 /*****************************************************************************/
1063 oslSignalAction SAL_CALL
osl_raiseSignal(sal_Int32 UserSignal
, void* UserData
)
1066 oslSignalAction Action
;
1069 bInitSignal
= InitSignal();
1071 osl_acquireMutex(SignalListMutex
);
1073 Info
.Signal
= osl_Signal_User
;
1074 Info
.UserSignal
= UserSignal
;
1075 Info
.UserData
= UserData
;
1077 Action
= CallSignalHandler(&Info
);
1079 osl_releaseMutex(SignalListMutex
);
1084 /*****************************************************************************/
1085 /* osl_setErrorReporting */
1086 /*****************************************************************************/
1087 sal_Bool SAL_CALL
osl_setErrorReporting( sal_Bool bEnable
)
1089 sal_Bool bOld
= bErrorReportingEnabled
;
1090 bErrorReportingEnabled
= bEnable
;