1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
33 #define MAX_STACK_FRAMES 256
38 #include "backtrace.h"
39 #define INCLUDE_BACKTRACE
40 #define STACKTYPE "MacOsX_X86"
48 #define INCLUDE_BACKTRACE
49 #define STACKTYPE "Linux"
54 #include "backtrace.h"
55 #define INCLUDE_BACKTRACE
58 #define STACKTYPE "Solaris_Sparc"
59 #elif defined( INTEL )
60 #define STACKTYPE "Solaris_X86"
62 #define STACKTYPE "Solaris_Unknown"
65 #endif /* defined SOLARIS */
67 #include <osl/diagnose.h>
68 #include <osl/mutex.h>
69 #include <osl/signal.h>
70 #include <osl/process.h>
71 #include <osl/thread.h>
72 #include <sal/macros.h>
73 #include <rtl/bootstrap.h>
74 #include <rtl/digest.h>
76 #include "file_path_helper.h"
82 #ifdef SAL_ENABLE_CRASH_REPORT
85 # define ACT_ABORT ACT_SYSTEM
88 #define MAX_PATH_LEN 2048
90 #if defined(HAVE_MEMCHECK_H)
94 typedef struct _oslSignalHandlerImpl
96 oslSignalHandlerFunction Handler
;
98 struct _oslSignalHandlerImpl
* pNext
;
99 } oslSignalHandlerImpl
;
101 static struct SignalAction
105 void (*Handler
)(int);
108 { SIGHUP
, ACT_IGNORE
, NULL
}, /* hangup */
109 { SIGINT
, ACT_EXIT
, NULL
}, /* interrupt (rubout) */
110 { SIGQUIT
, ACT_EXIT
, NULL
}, /* quit (ASCII FS) */
111 { SIGILL
, ACT_SYSTEM
, NULL
}, /* illegal instruction (not reset when caught) */
112 /* changed from ACT_ABOUT to ACT_SYSTEM to try and get collector to run*/
113 { SIGTRAP
, ACT_ABORT
, NULL
}, /* trace trap (not reset when caught) */
114 #if ( SIGIOT != SIGABRT )
115 { SIGIOT
, ACT_ABORT
, NULL
}, /* IOT instruction */
117 { SIGABRT
, ACT_ABORT
, NULL
}, /* used by abort, replace SIGIOT in the future */
119 { SIGEMT
, ACT_SYSTEM
, NULL
}, /* EMT instruction */
120 /* changed from ACT_ABORT to ACT_SYSTEM to remove handler*/
121 /* SIGEMT may also be used by the profiler - so it is probably not a good
122 plan to have the new handler use this signal*/
124 { SIGFPE
, ACT_ABORT
, NULL
}, /* floating point exception */
125 { SIGKILL
, ACT_SYSTEM
, NULL
}, /* kill (cannot be caught or ignored) */
126 { SIGBUS
, ACT_ABORT
, NULL
}, /* bus error */
127 { SIGSEGV
, ACT_ABORT
, NULL
}, /* segmentation violation */
129 { SIGSYS
, ACT_ABORT
, NULL
}, /* bad argument to system call */
131 { SIGPIPE
, ACT_HIDE
, NULL
}, /* write on a pipe with no one to read it */
132 { SIGALRM
, ACT_EXIT
, NULL
}, /* alarm clock */
133 { SIGTERM
, ACT_EXIT
, NULL
}, /* software termination signal from kill */
134 { SIGUSR1
, ACT_SYSTEM
, NULL
}, /* user defined signal 1 */
135 { SIGUSR2
, ACT_SYSTEM
, NULL
}, /* user defined signal 2 */
136 { SIGCHLD
, ACT_SYSTEM
, NULL
}, /* child status change */
138 { SIGPWR
, ACT_IGNORE
, NULL
}, /* power-fail restart */
140 { SIGWINCH
, ACT_IGNORE
, NULL
}, /* window size change */
141 { SIGURG
, ACT_EXIT
, NULL
}, /* urgent socket condition */
143 { SIGPOLL
, ACT_EXIT
, NULL
}, /* pollable event occurred */
145 { SIGSTOP
, ACT_SYSTEM
, NULL
}, /* stop (cannot be caught or ignored) */
146 { SIGTSTP
, ACT_SYSTEM
, NULL
}, /* user stop requested from tty */
147 { SIGCONT
, ACT_SYSTEM
, NULL
}, /* stopped process has been continued */
148 { SIGTTIN
, ACT_SYSTEM
, NULL
}, /* background tty read attempted */
149 { SIGTTOU
, ACT_SYSTEM
, NULL
}, /* background tty write attempted */
150 { SIGVTALRM
, ACT_EXIT
, NULL
}, /* virtual timer expired */
151 { SIGPROF
, ACT_SYSTEM
, NULL
}, /* profiling timer expired */
152 /*Change from ACT_EXIT to ACT_SYSTEM for SIGPROF is so that profiling signals do
153 not get taken by the new handler - the new handler does not pass on context
154 information which causes 'collect' to crash. This is a way of avoiding
155 what looks like a bug in the new handler*/
156 { SIGXCPU
, ACT_ABORT
, NULL
}, /* exceeded cpu limit */
157 { SIGXFSZ
, ACT_ABORT
, NULL
} /* exceeded file size limit */
159 const int NoSignals
= sizeof(Signals
) / sizeof(struct SignalAction
);
161 static sal_Bool bErrorReportingEnabled
= sal_True
;
162 static sal_Bool bInitSignal
= sal_False
;
163 static oslMutex SignalListMutex
;
164 static oslSignalHandlerImpl
* SignalList
;
165 static sal_Bool bDoHardKill
= sal_False
;
166 static sal_Bool bSetSEGVHandler
= sal_False
;
167 static sal_Bool bSetWINCHHandler
= sal_False
;
168 static sal_Bool bSetILLHandler
= sal_False
;
170 static void SignalHandlerFunction(int);
172 static void getExecutableName_Impl (rtl_String
** ppstrProgName
)
174 rtl_uString
* ustrProgFile
= 0;
175 osl_getExecutableFile (&ustrProgFile
);
178 rtl_uString
* ustrProgName
= 0;
179 osl_systemPathGetFileNameOrLastDirectoryPart (ustrProgFile
, &ustrProgName
);
180 if (ustrProgName
!= 0)
184 rtl_uString_getStr (ustrProgName
), rtl_uString_getLength (ustrProgName
),
185 osl_getThreadTextEncoding(),
186 OUSTRING_TO_OSTRING_CVTFLAGS
);
187 rtl_uString_release (ustrProgName
);
189 rtl_uString_release (ustrProgFile
);
193 static sal_Bool
is_soffice_Impl (void)
196 rtl_String
* strProgName
= 0;
198 getExecutableName_Impl (&strProgName
);
201 idx
= rtl_str_indexOfStr (rtl_string_getStr (strProgName
), "soffice");
202 rtl_string_release (strProgName
);
207 static sal_Bool
InitSignal()
210 struct sigaction act
;
211 struct sigaction oact
;
214 if (is_soffice_Impl())
218 rtl_uString
*ustrCommandArg
= 0;
220 argc
= osl_getCommandArgCount();
221 for ( argi
= 0; argi
< argc
; argi
++ )
223 if (osl_Process_E_None
== osl_getCommandArg (argi
, &ustrCommandArg
))
225 if (0 == rtl_ustr_ascii_compare (rtl_uString_getStr (ustrCommandArg
), "-bean"))
227 bDoHardKill
= sal_True
;
234 rtl_uString_release (ustrCommandArg
);
238 // WORKAROUND FOR SEGV HANDLER CONFLICT
240 // the java jit needs SIGSEGV for proper work
241 // and we need SIGSEGV for the office crashguard
243 // TEMPORARY SOLUTION:
244 // the office sets the signal handler during startup
245 // java can than overwrite it, if needed
246 bSetSEGVHandler
= sal_True
;
248 // WORKAROUND FOR WINCH HANDLER (SEE ABOVE)
249 bSetWINCHHandler
= sal_True
;
251 // WORKAROUND FOR ILLEGAL INSTRUCTION HANDLER (SEE ABOVE)
252 bSetILLHandler
= sal_True
;
256 bSetSEGVHandler
= bSetWINCHHandler
= bSetILLHandler
= bDoHardKill
= sal_False
;
259 SignalListMutex
= osl_createMutex();
261 act
.sa_handler
= SignalHandlerFunction
;
262 act
.sa_flags
= SA_RESTART
;
264 sigfillset(&(act
.sa_mask
));
266 /* Initialize the rest of the signals */
267 for (i
= 0; i
< NoSignals
; ++i
)
269 #if defined(HAVE_MEMCHECK_H)
270 if (Signals
[i
].Signal
== SIGUSR2
&& RUNNING_ON_VALGRIND
)
271 Signals
[i
].Action
= ACT_IGNORE
;
274 /* hack: stomcatd is attaching JavaVM wich dont work with an sigaction(SEGV) */
275 if ((bSetSEGVHandler
|| Signals
[i
].Signal
!= SIGSEGV
)
276 && (bSetWINCHHandler
|| Signals
[i
].Signal
!= SIGWINCH
)
277 && (bSetILLHandler
|| Signals
[i
].Signal
!= SIGILL
))
279 if (Signals
[i
].Action
!= ACT_SYSTEM
)
281 if (Signals
[i
].Action
== ACT_HIDE
)
283 struct sigaction ign
;
285 ign
.sa_handler
= SIG_IGN
;
287 sigemptyset(&ign
.sa_mask
);
289 if (sigaction(Signals
[i
].Signal
, &ign
, &oact
) == 0)
290 Signals
[i
].Handler
= oact
.sa_handler
;
292 Signals
[i
].Handler
= SIG_DFL
;
296 if (sigaction(Signals
[i
].Signal
, &act
, &oact
) == 0)
297 Signals
[i
].Handler
= oact
.sa_handler
;
299 Signals
[i
].Handler
= SIG_DFL
;
305 /* Clear signal mask inherited from parent process (on Mac OS X, upon a
306 crash soffice re-execs itself from within the signal handler, so the
307 second soffice would have the guilty signal blocked and would freeze upon
308 encountering a similar crash again): */
309 if (sigemptyset(&unset
) < 0 ||
310 pthread_sigmask(SIG_SETMASK
, &unset
, NULL
) < 0)
312 OSL_TRACE("sigemptyset or pthread_sigmask failed");
318 static sal_Bool
DeInitSignal()
321 struct sigaction act
;
324 sigemptyset(&(act
.sa_mask
));
326 /* Initialize the rest of the signals */
327 for (i
= NoSignals
- 1; i
>= 0; i
--)
328 if (Signals
[i
].Action
!= ACT_SYSTEM
)
330 act
.sa_handler
= Signals
[i
].Handler
;
332 sigaction(Signals
[i
].Signal
, &act
, NULL
);
335 osl_destroyMutex(SignalListMutex
);
340 #if defined (SAL_ENABLE_CRASH_REPORT) && defined(INCLUDE_BACKTRACE)
342 /*****************************************************************************/
343 /* Generate MD5 checksum */
344 /*****************************************************************************/
346 static sal_uInt32
calc_md5_checksum( const char *filename
, sal_uInt8
*pChecksum
, sal_uInt32 nChecksumLen
)
348 sal_uInt32 nBytesProcessed
= 0;
350 FILE *fp
= fopen( filename
, "r" );
354 rtlDigest digest
= rtl_digest_createMD5();
359 sal_uInt8 buffer
[4096];
360 rtlDigestError error
= rtl_Digest_E_None
;
362 while ( rtl_Digest_E_None
== error
&&
363 0 != (nBytesRead
= fread( buffer
, 1, sizeof(buffer
), fp
)) )
365 error
= rtl_digest_updateMD5( digest
, buffer
, nBytesRead
);
366 nBytesProcessed
+= nBytesRead
;
369 if ( rtl_Digest_E_None
== error
)
371 error
= rtl_digest_getMD5( digest
, pChecksum
, nChecksumLen
);
374 if ( rtl_Digest_E_None
!= error
)
377 rtl_digest_destroyMD5( digest
);
383 return nBytesProcessed
;
386 /*****************************************************************************/
387 /* Call crash reporter */
388 /*****************************************************************************/
390 /* Helper function to encode and write a string to a stream */
392 static int fputs_xml( const char *string
, FILE *stream
)
396 while ( result
>= 0 && *string
)
401 result
= fputs( "&", stream
);
404 result
= fputs( "<", stream
);
407 result
= fputs( ">", stream
);
410 result
= fputc( *string
, stream
);
421 /* Create intermediate files and run crash reporter */
423 #define REPORTENV_PARAM "-crashreportenv:"
425 #if defined SAL_ENABLE_CRASH_REPORT && defined INCLUDE_BACKTRACE && \
435 callback(struct dl_phdr_info
*info
, size_t size
, void *data
)
437 const ElfW(Phdr
) *pDynamic
= NULL
;
439 if (size
== sizeof(struct dl_phdr_info
))
442 for (i
= 0; i
< info
->dlpi_phnum
; ++i
)
444 if (info
->dlpi_phdr
[i
].p_type
== PT_DYNAMIC
)
446 pDynamic
= &(info
->dlpi_phdr
[i
]);
457 const char *dsoname
= info
->dlpi_name
;
459 dynamic_entry
* entry
= (dynamic_entry
*)data
;
461 if (strcmp(dsoname
, "") == 0)
463 snprintf(buffer
, sizeof(buffer
), "/proc/%d/exe", getpid());
464 if ((len
= readlink(buffer
, exe
, PATH_MAX
)) != -1)
471 if (strcmp(dsoname
, entry
->name
) == 0)
473 entry
->offset
= pDynamic
->p_offset
;
480 /* Get the location of the .dynamic section offset for the given elf file.
481 * i.e. same as the "Offset" value shown for DYNAMIC from readelf -l foo
483 * We want to know this value so that if the binaries have been modifed
484 * by prelink then we can still process the call stack on server side
485 * by comparing this value to that of an "un-prelinked but known to be
486 * otherwise equivalent" version of those binaries and adjust the call
487 * stack addresses by the differences between .dynamic addresses so as
488 * to be able to map the prelinked addresses back to the unprelinked
494 dynamic_section_offset(const char *name
)
501 dl_iterate_phdr(callback
, &entry
);
507 static int ReportCrash( int Signal
)
509 #ifdef SAL_ENABLE_CRASH_REPORT
510 static sal_Bool bCrashReporterExecuted
= sal_False
;
511 sal_Bool bAutoCrashReport
= sal_False
;
515 rtl_uString
*ustrCommandArg
= NULL
;
517 if ( !bErrorReportingEnabled
)
520 argc
= osl_getCommandArgCount();
522 for ( argi
= 0; argi
< argc
; argi
++ )
524 if ( osl_Process_E_None
== osl_getCommandArg( argi
, &ustrCommandArg
) )
526 if ( 0 == rtl_ustr_ascii_compare( rtl_uString_getStr( ustrCommandArg
), "--nocrashreport" ) )
528 rtl_uString_release( ustrCommandArg
);
531 else if ( 0 == rtl_ustr_ascii_compare( rtl_uString_getStr( ustrCommandArg
), "--autocrashreport" ) )
533 bAutoCrashReport
= sal_True
;
535 else if ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength(
536 rtl_uString_getStr( ustrCommandArg
), rtl_uString_getLength( ustrCommandArg
),
537 REPORTENV_PARAM
, strlen(REPORTENV_PARAM
) )
540 rtl_uString
*ustrEnvironment
= NULL
;
541 rtl_String
*strEnv
= NULL
;
543 rtl_uString_newFromStr( &ustrEnvironment
, rtl_uString_getStr( ustrCommandArg
) + strlen(REPORTENV_PARAM
) );
545 if ( ustrEnvironment
)
549 rtl_uString_getStr( ustrEnvironment
), rtl_uString_getLength( ustrEnvironment
),
550 osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS
555 putenv( rtl_string_getStr( strEnv
) );
556 rtl_string_release( strEnv
);
559 rtl_uString_release( ustrEnvironment
);
567 if ( ustrCommandArg
)
568 rtl_uString_release( ustrCommandArg
);
570 if ( !bCrashReporterExecuted
)
573 /* struct sigaction act; */
575 for (i
= 0; i
< NoSignals
; i
++)
577 if (Signals
[i
].Signal
== Signal
&& Signals
[i
].Action
== ACT_ABORT
)
580 char szShellCmd
[512] = { '\0' };
581 char *pXMLTempName
= NULL
;
582 char *pStackTempName
= NULL
;
583 char *pChecksumTempName
= NULL
;
585 #ifdef INCLUDE_BACKTRACE
586 char szXMLTempNameBuffer
[L_tmpnam
];
587 char szChecksumTempNameBuffer
[L_tmpnam
];
588 char szStackTempNameBuffer
[L_tmpnam
];
590 void *stackframes
[MAX_STACK_FRAMES
];
592 int nFrames
= backtrace( stackframes
, SAL_N_ELEMENTS(stackframes
) );
594 FILE *xmlout
= NULL
, *stackout
= NULL
, *checksumout
= NULL
;
595 int fdxml
, fdstk
, fdchksum
;
597 strncpy( szXMLTempNameBuffer
, P_tmpdir
, sizeof(szXMLTempNameBuffer
) );
598 strncat( szXMLTempNameBuffer
, "/crxmlXXXXXX", sizeof(szXMLTempNameBuffer
) );
600 strncpy( szStackTempNameBuffer
, P_tmpdir
, sizeof(szStackTempNameBuffer
) );
601 strncat( szStackTempNameBuffer
, "/crstkXXXXXX", sizeof(szStackTempNameBuffer
) );
603 strncpy( szChecksumTempNameBuffer
, P_tmpdir
, sizeof(szChecksumTempNameBuffer
) );
604 strncat( szChecksumTempNameBuffer
, "/crchkXXXXXX", sizeof(szChecksumTempNameBuffer
) );
606 fdxml
= mkstemp(szXMLTempNameBuffer
);
607 fdstk
= mkstemp(szStackTempNameBuffer
);
608 fdchksum
= mkstemp(szChecksumTempNameBuffer
);
610 xmlout
= fdopen( fdxml
, "w" );
611 stackout
= fdopen( fdstk
, "w" );
612 checksumout
= fdopen( fdchksum
, "w" );
614 pXMLTempName
= szXMLTempNameBuffer
;
615 pStackTempName
= szStackTempNameBuffer
;
616 pChecksumTempName
= szChecksumTempNameBuffer
;
619 if ( xmlout
&& stackout
&& checksumout
)
621 fprintf( xmlout
, "<errormail:Stack type=\"%s\">\n", STACKTYPE
);
623 fprintf( checksumout
, "<errormail:Checksums type=\"MD5\">\n" );
625 for ( iFrame
= 0; iFrame
< nFrames
; iFrame
++ )
629 fprintf( stackout
, "0x%" SAL_PRIxUINTPTR
":",
630 SAL_INT_CAST(sal_uIntPtr
, stackframes
[iFrame
]) );
632 fprintf( xmlout
, "<errormail:StackInfo pos=\"%d\" ip=\"0x%" SAL_PRIxUINTPTR
"\"",
634 SAL_INT_CAST(sal_uIntPtr
, stackframes
[iFrame
])
637 memset( &dl_info
, 0, sizeof(dl_info
) );
639 /* dladdr may fail */
640 if ( dladdr( stackframes
[iFrame
], &dl_info
) )
642 const char *dli_fname
= NULL
;
643 char *dli_fdir
= NULL
;
644 char szDirectory
[PATH_MAX
];
645 char szCanonicDirectory
[PATH_MAX
];
647 /* Don't expect that dladdr filled all members of dl_info */
649 dli_fname
= dl_info
.dli_fname
? strrchr( dl_info
.dli_fname
, '/' ) : NULL
;
653 memcpy( szDirectory
, dl_info
.dli_fname
, dli_fname
- dl_info
.dli_fname
);
654 szDirectory
[dli_fname
- dl_info
.dli_fname
] = 0;
656 dli_fdir
= realpath( szDirectory
, szCanonicDirectory
) ? szCanonicDirectory
: szDirectory
;
658 if ( *dli_fdir
&& dli_fdir
[ strlen(dli_fdir
) - 1 ] != '/' )
659 strcat( dli_fdir
, "/" );
662 dli_fname
= dl_info
.dli_fname
;
664 /* create checksum of library on stack */
667 sal_uInt8 checksum
[RTL_DIGEST_LENGTH_MD5
];
669 sal_uInt32 nBytesProcessed
= calc_md5_checksum(
670 dl_info
.dli_fname
, checksum
, sizeof(checksum
) );
671 if ( nBytesProcessed
)
675 fprintf( checksumout
, "<errormail:Checksum sum=\"0x" );
676 for ( j
= 0; j
< 16; fprintf( checksumout
, "%02X", checksum
[j
++] ) );
677 fprintf( checksumout
,
678 "\" bytes=\"%lu\" file=\"%s\"/>\n",
680 unsigned long, nBytesProcessed
),
685 if ( dl_info
.dli_fbase
&& dl_info
.dli_fname
)
688 ElfW(Off
) dynamic_offset
= dynamic_section_offset(dl_info
.dli_fname
);
689 fprintf( stackout
, " 0x%" SAL_PRI_SIZET
"x:", dynamic_offset
);
692 fprintf( stackout
, " %s + 0x%" SAL_PRI_PTRDIFFT
"x",
694 (char*)stackframes
[iFrame
] - (char*)dl_info
.dli_fbase
697 fprintf( xmlout
, " rel=\"0x%" SAL_PRI_PTRDIFFT
"x\"", (char *)stackframes
[iFrame
] - (char *)dl_info
.dli_fbase
);
699 fprintf( xmlout
, " name=\"%s\"", dli_fname
);
702 fprintf( xmlout
, " path=\"%s\"", dli_fdir
);
705 fprintf( xmlout
, " dynamicoffset=\"0x%" SAL_PRI_SIZET
"x\"", dynamic_offset
);
709 fprintf( stackout
, " ????????" );
711 if ( dl_info
.dli_sname
&& dl_info
.dli_saddr
)
713 fputs( " (", stackout
);
714 fputs_xml( dl_info
.dli_sname
, stackout
);
715 fprintf( stackout
, " + 0x%" SAL_PRI_PTRDIFFT
"x)",
716 (char*)stackframes
[iFrame
] - (char*)dl_info
.dli_saddr
);
718 fputs( " ordinal=\"", xmlout
);
719 fputs_xml( dl_info
.dli_sname
, xmlout
);
720 fprintf( xmlout
, "+0x%" SAL_PRI_PTRDIFFT
"x\"",
721 (char *)stackframes
[iFrame
] - (char *)dl_info
.dli_saddr
);
725 else /* dladdr failed */
727 fprintf( stackout
, " ????????" );
730 fprintf( stackout
, "\n" );
731 fprintf( xmlout
, "/>\n" );
735 fprintf( xmlout
, "</errormail:Stack>\n" );
736 fprintf( checksumout
, "</errormail:Checksums>\n" );
741 pStackTempName
= NULL
;
742 pChecksumTempName
= NULL
;
750 fclose( checksumout
);
752 if ( pXMLTempName
&& pChecksumTempName
&& pStackTempName
)
753 #endif /* INCLUDE_BACKTRACE */
755 rtl_uString
* crashrep_url
= NULL
;
756 rtl_uString
* crashrep_path
= NULL
;
757 rtl_String
* crashrep_path_system
= NULL
;
760 RTL_CONSTASCII_USTRINGPARAM(
761 "$BRAND_BASE_DIR/program/crashrep"),
762 OSTRING_TO_OUSTRING_CVTFLAGS
);
763 rtl_bootstrap_expandMacros(&crashrep_url
);
764 osl_getSystemPathFromFileURL(crashrep_url
, &crashrep_path
);
766 &crashrep_path_system
,
767 rtl_uString_getStr(crashrep_path
),
768 rtl_uString_getLength(crashrep_path
),
769 osl_getThreadTextEncoding(),
770 (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
771 | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR
));
772 rtl_uString_release(crashrep_url
);
773 rtl_uString_release(crashrep_path
);
774 #if defined INCLUDE_BACKTRACE && (defined LINUX || defined MACOSX)
775 snprintf( szShellCmd
, SAL_N_ELEMENTS(szShellCmd
),
776 "%s -p %d -s %d -xml %s -chksum %s -stack %s -noui%s",
777 rtl_string_getStr(crashrep_path_system
),
783 bAutoCrashReport
? " -send" : "" );
784 #elif defined INCLUDE_BACKTRACE && defined SOLARIS
785 snprintf( szShellCmd
, SAL_N_ELEMENTS(szShellCmd
),
786 "%s -p %d -s %d -xml %s -chksum %s -noui%s",
787 rtl_string_getStr(crashrep_path_system
),
792 bAutoCrashReport
? " -send" : "" );
794 snprintf( szShellCmd
, SAL_N_ELEMENTS(szShellCmd
),
795 "%s -p %d -s %d -noui%s",
796 rtl_string_getStr(crashrep_path_system
),
797 getpid(), Signal
, bAutoCrashReport
? " -send" : "" );
799 rtl_string_release(crashrep_path_system
);
802 ret
= szShellCmd
[0] == '\0' ? -1 : system( szShellCmd
);
805 unlink( pXMLTempName
);
807 if ( pStackTempName
)
808 unlink( pStackTempName
);
810 if ( pChecksumTempName
)
811 unlink( pChecksumTempName
);
815 bCrashReporterExecuted
= sal_True
;
828 #else /* defined SAL_ENABLE_CRASH_REPORT */
829 /* the utility crash_report is not build, so do the same as when
830 the option -nocrashreport is used */
831 (void) Signal
; // avoid warnings
833 #endif /* defined SAL_ENABLE_CRASH_REPORT */
836 static void PrintStack( int sig
)
838 #ifdef INCLUDE_BACKTRACE
839 void *buffer
[MAX_STACK_FRAMES
];
840 int size
= backtrace( buffer
, SAL_N_ELEMENTS(buffer
) );
843 fprintf( stderr
, "\n\nFatal exception: Signal %d\n", sig
);
845 #if defined( MACOSX ) && !defined( INCLUDE_BACKTRACE )
846 fprintf( stderr
, "Please turn on Enable Crash Reporting and\nAutomatic Display of Crashlogs in the Console application\n" );
848 #ifdef INCLUDE_BACKTRACE
851 fputs( "Stack:\n", stderr
);
852 backtrace_symbols_fd( buffer
, size
, fileno(stderr
) );
858 static oslSignalAction
CallSignalHandler(oslSignalInfo
*pInfo
)
860 oslSignalHandlerImpl
* pHandler
= SignalList
;
861 oslSignalAction Action
= osl_Signal_ActCallNextHdl
;
863 while (pHandler
!= NULL
)
865 if ((Action
= pHandler
->Handler(pHandler
->pData
, pInfo
))
866 != osl_Signal_ActCallNextHdl
)
869 pHandler
= pHandler
->pNext
;
875 void CallSystemHandler(int Signal
)
878 struct sigaction act
;
880 for (i
= 0; i
< NoSignals
; i
++)
882 if (Signals
[i
].Signal
== Signal
)
888 if ((Signals
[i
].Handler
== NULL
) ||
889 (Signals
[i
].Handler
== SIG_DFL
) ||
890 (Signals
[i
].Handler
== SIG_IGN
) ||
891 (Signals
[i
].Handler
== SIG_ERR
))
893 switch (Signals
[i
].Action
)
895 case ACT_EXIT
: /* terminate */
896 /* prevent dumping core on exit() */
900 case ACT_ABORT
: /* terminate witch core dump */
901 ReportCrash( Signal
);
902 act
.sa_handler
= SIG_DFL
;
904 sigemptyset(&(act
.sa_mask
));
905 sigaction(SIGABRT
, &act
, NULL
);
906 PrintStack( Signal
);
910 case ACT_IGNORE
: /* ignore */
913 default: /* should never happen */
918 (*Signals
[i
].Handler
)(Signal
);
922 #if defined(HAVE_MEMCHECK_H)
923 static void DUMPCURRENTALLOCS()
925 VALGRIND_PRINTF( "=== start memcheck dump of active allocations ===\n" );
927 #if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
928 # pragma GCC diagnostic push
929 # pragma GCC diagnostic ignored "-Wunused-but-set-variable"
932 VALGRIND_DO_LEAK_CHECK
;
934 #if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
935 # pragma GCC diagnostic pop
938 VALGRIND_PRINTF( "=== end memcheck dump of active allocations ===\n" );
942 /*****************************************************************************/
943 /* SignalHandlerFunction */
944 /*****************************************************************************/
945 void SignalHandlerFunction(int Signal
)
948 struct sigaction act
;
950 Info
.UserSignal
= Signal
;
951 Info
.UserData
= NULL
;
959 #if ( SIGIOT != SIGABRT )
962 Info
.Signal
= osl_Signal_AccessViolation
;
966 Info
.Signal
= osl_Signal_IntegerDivideByZero
;
970 Info
.Signal
= osl_Signal_FloatDivideByZero
;
977 Info
.Signal
= osl_Signal_Terminate
;
980 #if defined(HAVE_MEMCHECK_H)
982 if (RUNNING_ON_VALGRIND
)
984 Info
.Signal
= osl_Signal_System
;
989 Info
.Signal
= osl_Signal_System
;
993 ReportCrash( Signal
);
995 /* Portal Demo HACK !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
996 if (bDoHardKill
&& (Info
.Signal
== osl_Signal_AccessViolation
))
998 /* Portal Demo HACK !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
1001 switch (CallSignalHandler(&Info
))
1003 case osl_Signal_ActCallNextHdl
:
1004 CallSystemHandler(Signal
);
1007 case osl_Signal_ActAbortApp
:
1008 ReportCrash( Signal
);
1009 act
.sa_handler
= SIG_DFL
;
1011 sigemptyset(&(act
.sa_mask
));
1012 sigaction(SIGABRT
, &act
, NULL
);
1013 PrintStack( Signal
);
1017 case osl_Signal_ActKillApp
:
1018 /* prevent dumping core on exit() */
1026 /*****************************************************************************/
1027 /* osl_addSignalHandler */
1028 /*****************************************************************************/
1029 oslSignalHandler SAL_CALL
osl_addSignalHandler(oslSignalHandlerFunction Handler
, void* pData
)
1031 oslSignalHandlerImpl
* pHandler
;
1033 OSL_ASSERT(Handler
!= NULL
);
1040 bInitSignal
= InitSignal();
1042 pHandler
= (oslSignalHandlerImpl
*) calloc(1, sizeof(oslSignalHandlerImpl
));
1044 if (pHandler
!= NULL
)
1046 pHandler
->Handler
= Handler
;
1047 pHandler
->pData
= pData
;
1049 osl_acquireMutex(SignalListMutex
);
1051 pHandler
->pNext
= SignalList
;
1052 SignalList
= pHandler
;
1054 osl_releaseMutex(SignalListMutex
);
1062 /*****************************************************************************/
1063 /* osl_removeSignalHandler */
1064 /*****************************************************************************/
1065 sal_Bool SAL_CALL
osl_removeSignalHandler(oslSignalHandler Handler
)
1067 oslSignalHandlerImpl
*pHandler
, *pPrevious
= NULL
;
1069 OSL_ASSERT(Handler
!= NULL
);
1072 bInitSignal
= InitSignal();
1074 osl_acquireMutex(SignalListMutex
);
1076 pHandler
= SignalList
;
1078 while (pHandler
!= NULL
)
1080 if (pHandler
== Handler
)
1083 pPrevious
->pNext
= pHandler
->pNext
;
1085 SignalList
= pHandler
->pNext
;
1087 osl_releaseMutex(SignalListMutex
);
1089 if (SignalList
== NULL
)
1090 bInitSignal
= DeInitSignal();
1097 pPrevious
= pHandler
;
1098 pHandler
= pHandler
->pNext
;
1101 osl_releaseMutex(SignalListMutex
);
1106 /*****************************************************************************/
1107 /* osl_raiseSignal */
1108 /*****************************************************************************/
1109 oslSignalAction SAL_CALL
osl_raiseSignal(sal_Int32 UserSignal
, void* UserData
)
1112 oslSignalAction Action
;
1115 bInitSignal
= InitSignal();
1117 osl_acquireMutex(SignalListMutex
);
1119 Info
.Signal
= osl_Signal_User
;
1120 Info
.UserSignal
= UserSignal
;
1121 Info
.UserData
= UserData
;
1123 Action
= CallSignalHandler(&Info
);
1125 osl_releaseMutex(SignalListMutex
);
1130 /*****************************************************************************/
1131 /* osl_setErrorReporting */
1132 /*****************************************************************************/
1133 sal_Bool SAL_CALL
osl_setErrorReporting( sal_Bool bEnable
)
1135 sal_Bool bOld
= bErrorReportingEnabled
;
1136 bErrorReportingEnabled
= bEnable
;
1141 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */