1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
27 #include "backtrace.h"
28 #define INCLUDE_BACKTRACE
29 #ifdef SAL_ENABLE_CRASH_REPORT
30 #define STACKTYPE "MacOsX_X86"
39 #define INCLUDE_BACKTRACE
40 #if defined SAL_ENABLE_CRASH_REPORT
41 #define STACKTYPE "Linux"
47 #include "backtrace.h"
48 #define INCLUDE_BACKTRACE
50 #if defined SAL_ENABLE_CRASH_REPORT
52 #define STACKTYPE "Solaris_Sparc"
53 #elif defined( INTEL )
54 #define STACKTYPE "Solaris_X86"
56 #define STACKTYPE "Solaris_Unknown"
60 #endif /* defined SOLARIS */
62 #if defined INCLUDE_BACKTRACE
63 #define MAX_STACK_FRAMES 256
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 <sal/macros.h>
72 #include <rtl/bootstrap.h>
73 #include <rtl/digest.h>
75 #include "file_path_helper.h"
81 #ifdef SAL_ENABLE_CRASH_REPORT
84 # define ACT_ABORT ACT_SYSTEM
87 #if defined HAVE_VALGRIND_HEADERS
88 #include <valgrind/memcheck.h>
91 typedef struct _oslSignalHandlerImpl
93 oslSignalHandlerFunction Handler
;
95 struct _oslSignalHandlerImpl
* pNext
;
96 } oslSignalHandlerImpl
;
98 static struct SignalAction
102 void (*Handler
)(int);
105 { SIGHUP
, ACT_HIDE
, NULL
}, /* hangup */
106 { SIGINT
, ACT_EXIT
, NULL
}, /* interrupt (rubout) */
107 { SIGQUIT
, ACT_EXIT
, NULL
}, /* quit (ASCII FS) */
108 { SIGILL
, ACT_SYSTEM
, NULL
}, /* illegal instruction (not reset when caught) */
109 /* changed from ACT_ABOUT to ACT_SYSTEM to try and get collector to run*/
110 { SIGTRAP
, ACT_ABORT
, NULL
}, /* trace trap (not reset when caught) */
111 #if ( SIGIOT != SIGABRT )
112 { SIGIOT
, ACT_ABORT
, NULL
}, /* IOT instruction */
114 { SIGABRT
, ACT_ABORT
, NULL
}, /* used by abort, replace SIGIOT in the future */
116 { SIGEMT
, ACT_SYSTEM
, NULL
}, /* EMT instruction */
117 /* changed from ACT_ABORT to ACT_SYSTEM to remove handler*/
118 /* SIGEMT may also be used by the profiler - so it is probably not a good
119 plan to have the new handler use this signal*/
121 { SIGFPE
, ACT_ABORT
, NULL
}, /* floating point exception */
122 { SIGKILL
, ACT_SYSTEM
, NULL
}, /* kill (cannot be caught or ignored) */
123 { SIGBUS
, ACT_ABORT
, NULL
}, /* bus error */
124 { SIGSEGV
, ACT_ABORT
, NULL
}, /* segmentation violation */
126 { SIGSYS
, ACT_ABORT
, NULL
}, /* bad argument to system call */
128 { SIGPIPE
, ACT_HIDE
, NULL
}, /* write on a pipe with no one to read it */
129 { SIGALRM
, ACT_EXIT
, NULL
}, /* alarm clock */
130 { SIGTERM
, ACT_EXIT
, NULL
}, /* software termination signal from kill */
131 { SIGUSR1
, ACT_SYSTEM
, NULL
}, /* user defined signal 1 */
132 { SIGUSR2
, ACT_SYSTEM
, NULL
}, /* user defined signal 2 */
133 { SIGCHLD
, ACT_SYSTEM
, NULL
}, /* child status change */
135 { SIGPWR
, ACT_IGNORE
, NULL
}, /* power-fail restart */
137 { SIGWINCH
, ACT_IGNORE
, NULL
}, /* window size change */
138 { SIGURG
, ACT_EXIT
, NULL
}, /* urgent socket condition */
140 { SIGPOLL
, ACT_EXIT
, NULL
}, /* pollable event occurred */
142 { SIGSTOP
, ACT_SYSTEM
, NULL
}, /* stop (cannot be caught or ignored) */
143 { SIGTSTP
, ACT_SYSTEM
, NULL
}, /* user stop requested from tty */
144 { SIGCONT
, ACT_SYSTEM
, NULL
}, /* stopped process has been continued */
145 { SIGTTIN
, ACT_SYSTEM
, NULL
}, /* background tty read attempted */
146 { SIGTTOU
, ACT_SYSTEM
, NULL
}, /* background tty write attempted */
147 { SIGVTALRM
, ACT_EXIT
, NULL
}, /* virtual timer expired */
148 { SIGPROF
, ACT_SYSTEM
, NULL
}, /* profiling timer expired */
149 /*Change from ACT_EXIT to ACT_SYSTEM for SIGPROF is so that profiling signals do
150 not get taken by the new handler - the new handler does not pass on context
151 information which causes 'collect' to crash. This is a way of avoiding
152 what looks like a bug in the new handler*/
153 { SIGXCPU
, ACT_ABORT
, NULL
}, /* exceeded cpu limit */
154 { SIGXFSZ
, ACT_ABORT
, NULL
} /* exceeded file size limit */
156 const int NoSignals
= sizeof(Signals
) / sizeof(struct SignalAction
);
158 static sal_Bool bErrorReportingEnabled
= sal_True
;
159 static sal_Bool bInitSignal
= sal_False
;
160 static oslMutex SignalListMutex
;
161 static oslSignalHandlerImpl
* SignalList
;
162 static sal_Bool bDoHardKill
= sal_False
;
163 static sal_Bool bSetSEGVHandler
= sal_False
;
164 static sal_Bool bSetWINCHHandler
= sal_False
;
165 static sal_Bool bSetILLHandler
= sal_False
;
167 static void SignalHandlerFunction(int);
169 static void getExecutableName_Impl (rtl_String
** ppstrProgName
)
171 rtl_uString
* ustrProgFile
= 0;
172 osl_getExecutableFile (&ustrProgFile
);
175 rtl_uString
* ustrProgName
= 0;
176 osl_systemPathGetFileNameOrLastDirectoryPart (ustrProgFile
, &ustrProgName
);
177 if (ustrProgName
!= 0)
181 rtl_uString_getStr (ustrProgName
), rtl_uString_getLength (ustrProgName
),
182 osl_getThreadTextEncoding(),
183 OUSTRING_TO_OSTRING_CVTFLAGS
);
184 rtl_uString_release (ustrProgName
);
186 rtl_uString_release (ustrProgFile
);
190 static sal_Bool
is_soffice_Impl (void)
193 rtl_String
* strProgName
= 0;
195 getExecutableName_Impl (&strProgName
);
198 idx
= rtl_str_indexOfStr (rtl_string_getStr (strProgName
), "soffice");
199 rtl_string_release (strProgName
);
204 static sal_Bool
InitSignal()
207 struct sigaction act
;
208 struct sigaction oact
;
211 if (is_soffice_Impl())
215 rtl_uString
*ustrCommandArg
= 0;
217 argc
= osl_getCommandArgCount();
218 for ( argi
= 0; argi
< argc
; argi
++ )
220 if (osl_Process_E_None
== osl_getCommandArg (argi
, &ustrCommandArg
))
222 if (0 == rtl_ustr_ascii_compare (rtl_uString_getStr (ustrCommandArg
), "-bean"))
224 bDoHardKill
= sal_True
;
231 rtl_uString_release (ustrCommandArg
);
235 // WORKAROUND FOR SEGV HANDLER CONFLICT
237 // the java jit needs SIGSEGV for proper work
238 // and we need SIGSEGV for the office crashguard
240 // TEMPORARY SOLUTION:
241 // the office sets the signal handler during startup
242 // java can than overwrite it, if needed
243 bSetSEGVHandler
= sal_True
;
245 // WORKAROUND FOR WINCH HANDLER (SEE ABOVE)
246 bSetWINCHHandler
= sal_True
;
248 // WORKAROUND FOR ILLEGAL INSTRUCTION HANDLER (SEE ABOVE)
249 bSetILLHandler
= sal_True
;
253 bSetSEGVHandler
= bSetWINCHHandler
= bSetILLHandler
= bDoHardKill
= sal_False
;
256 SignalListMutex
= osl_createMutex();
258 act
.sa_handler
= SignalHandlerFunction
;
259 act
.sa_flags
= SA_RESTART
;
261 sigfillset(&(act
.sa_mask
));
263 /* Initialize the rest of the signals */
264 for (i
= 0; i
< NoSignals
; ++i
)
266 #if defined HAVE_VALGRIND_HEADERS
267 if (Signals
[i
].Signal
== SIGUSR2
&& RUNNING_ON_VALGRIND
)
268 Signals
[i
].Action
= ACT_IGNORE
;
271 /* hack: stomcatd is attaching JavaVM which does not work with an sigaction(SEGV) */
272 if ((bSetSEGVHandler
|| Signals
[i
].Signal
!= SIGSEGV
)
273 && (bSetWINCHHandler
|| Signals
[i
].Signal
!= SIGWINCH
)
274 && (bSetILLHandler
|| Signals
[i
].Signal
!= SIGILL
))
276 if (Signals
[i
].Action
!= ACT_SYSTEM
)
278 if (Signals
[i
].Action
== ACT_HIDE
)
280 struct sigaction ign
;
282 ign
.sa_handler
= SIG_IGN
;
284 sigemptyset(&ign
.sa_mask
);
286 if (sigaction(Signals
[i
].Signal
, &ign
, &oact
) == 0)
287 Signals
[i
].Handler
= oact
.sa_handler
;
289 Signals
[i
].Handler
= SIG_DFL
;
293 if (sigaction(Signals
[i
].Signal
, &act
, &oact
) == 0)
294 Signals
[i
].Handler
= oact
.sa_handler
;
296 Signals
[i
].Handler
= SIG_DFL
;
302 /* Clear signal mask inherited from parent process (on Mac OS X, upon a
303 crash soffice re-execs itself from within the signal handler, so the
304 second soffice would have the guilty signal blocked and would freeze upon
305 encountering a similar crash again): */
306 if (sigemptyset(&unset
) < 0 ||
307 pthread_sigmask(SIG_SETMASK
, &unset
, NULL
) < 0)
309 OSL_TRACE("sigemptyset or pthread_sigmask failed");
315 static sal_Bool
DeInitSignal()
318 struct sigaction act
;
321 sigemptyset(&(act
.sa_mask
));
323 /* Initialize the rest of the signals */
324 for (i
= NoSignals
- 1; i
>= 0; i
--)
325 if (Signals
[i
].Action
!= ACT_SYSTEM
)
327 act
.sa_handler
= Signals
[i
].Handler
;
329 sigaction(Signals
[i
].Signal
, &act
, NULL
);
332 osl_destroyMutex(SignalListMutex
);
337 #if defined (SAL_ENABLE_CRASH_REPORT) && defined(INCLUDE_BACKTRACE)
339 static sal_uInt32
calc_md5_checksum( const char *filename
, sal_uInt8
*pChecksum
, sal_uInt32 nChecksumLen
)
341 sal_uInt32 nBytesProcessed
= 0;
343 FILE *fp
= fopen( filename
, "r" );
347 rtlDigest digest
= rtl_digest_createMD5();
352 sal_uInt8 buffer
[4096];
353 rtlDigestError error
= rtl_Digest_E_None
;
355 while ( rtl_Digest_E_None
== error
&&
356 0 != (nBytesRead
= fread( buffer
, 1, sizeof(buffer
), fp
)) )
358 error
= rtl_digest_updateMD5( digest
, buffer
, nBytesRead
);
359 nBytesProcessed
+= nBytesRead
;
362 if ( rtl_Digest_E_None
== error
)
364 error
= rtl_digest_getMD5( digest
, pChecksum
, nChecksumLen
);
367 if ( rtl_Digest_E_None
!= error
)
370 rtl_digest_destroyMD5( digest
);
376 return nBytesProcessed
;
379 /*****************************************************************************/
380 /* Call crash reporter */
381 /*****************************************************************************/
383 /* Helper function to encode and write a string to a stream */
385 static int fputs_xml( const char *string
, FILE *stream
)
389 while ( result
>= 0 && *string
)
394 result
= fputs( "&", stream
);
397 result
= fputs( "<", stream
);
400 result
= fputs( ">", stream
);
403 result
= fputc( *string
, stream
);
414 /* Create intermediate files and run crash reporter */
416 #if defined SAL_ENABLE_CRASH_REPORT && defined INCLUDE_BACKTRACE && \
426 callback(struct dl_phdr_info
*info
, size_t size
, void *data
)
428 const ElfW(Phdr
) *pDynamic
= NULL
;
430 if (size
== sizeof(struct dl_phdr_info
))
433 for (i
= 0; i
< info
->dlpi_phnum
; ++i
)
435 if (info
->dlpi_phdr
[i
].p_type
== PT_DYNAMIC
)
437 pDynamic
= &(info
->dlpi_phdr
[i
]);
448 const char *dsoname
= info
->dlpi_name
;
450 dynamic_entry
* entry
= (dynamic_entry
*)data
;
452 if (strcmp(dsoname
, "") == 0)
454 snprintf(buffer
, sizeof(buffer
), "/proc/%d/exe", getpid());
455 if ((len
= readlink(buffer
, exe
, PATH_MAX
)) != -1)
462 if (strcmp(dsoname
, entry
->name
) == 0)
464 entry
->offset
= pDynamic
->p_offset
;
471 /* Get the location of the .dynamic section offset for the given elf file.
472 * i.e. same as the "Offset" value shown for DYNAMIC from readelf -l foo
474 * We want to know this value so that if the binaries have been modifed
475 * by prelink then we can still process the call stack on server side
476 * by comparing this value to that of an "un-prelinked but known to be
477 * otherwise equivalent" version of those binaries and adjust the call
478 * stack addresses by the differences between .dynamic addresses so as
479 * to be able to map the prelinked addresses back to the unprelinked
485 dynamic_section_offset(const char *name
)
492 dl_iterate_phdr(callback
, &entry
);
498 static int ReportCrash( int Signal
)
500 #ifdef SAL_ENABLE_CRASH_REPORT
502 #define REPORTENV_PARAM "-crashreportenv:"
504 static sal_Bool bCrashReporterExecuted
= sal_False
;
505 sal_Bool bAutoCrashReport
= sal_False
;
509 rtl_uString
*ustrCommandArg
= NULL
;
511 if ( !bErrorReportingEnabled
)
514 argc
= osl_getCommandArgCount();
516 for ( argi
= 0; argi
< argc
; argi
++ )
518 if ( osl_Process_E_None
== osl_getCommandArg( argi
, &ustrCommandArg
) )
520 if ( 0 == rtl_ustr_ascii_compare( rtl_uString_getStr( ustrCommandArg
), "--nocrashreport" ) )
522 rtl_uString_release( ustrCommandArg
);
525 else if ( 0 == rtl_ustr_ascii_compare( rtl_uString_getStr( ustrCommandArg
), "--autocrashreport" ) )
527 bAutoCrashReport
= sal_True
;
529 else if ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength(
530 rtl_uString_getStr( ustrCommandArg
), rtl_uString_getLength( ustrCommandArg
),
531 REPORTENV_PARAM
, strlen(REPORTENV_PARAM
) )
534 rtl_uString
*ustrEnvironment
= NULL
;
535 rtl_String
*strEnv
= NULL
;
537 rtl_uString_newFromStr( &ustrEnvironment
, rtl_uString_getStr( ustrCommandArg
) + strlen(REPORTENV_PARAM
) );
539 if ( ustrEnvironment
)
543 rtl_uString_getStr( ustrEnvironment
), rtl_uString_getLength( ustrEnvironment
),
544 osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS
549 putenv( rtl_string_getStr( strEnv
) );
550 rtl_string_release( strEnv
);
553 rtl_uString_release( ustrEnvironment
);
561 if ( ustrCommandArg
)
562 rtl_uString_release( ustrCommandArg
);
564 if ( !bCrashReporterExecuted
)
567 /* struct sigaction act; */
569 for (i
= 0; i
< NoSignals
; i
++)
571 if (Signals
[i
].Signal
== Signal
&& Signals
[i
].Action
== ACT_ABORT
)
574 char szShellCmd
[512] = { '\0' };
575 char *pXMLTempName
= NULL
;
576 char *pStackTempName
= NULL
;
577 char *pChecksumTempName
= NULL
;
579 #ifdef INCLUDE_BACKTRACE
580 char szXMLTempNameBuffer
[L_tmpnam
];
581 char szChecksumTempNameBuffer
[L_tmpnam
];
582 char szStackTempNameBuffer
[L_tmpnam
];
584 void *stackframes
[MAX_STACK_FRAMES
];
586 int nFrames
= backtrace( stackframes
, SAL_N_ELEMENTS(stackframes
) );
588 FILE *xmlout
= NULL
, *stackout
= NULL
, *checksumout
= NULL
;
589 int fdxml
, fdstk
, fdchksum
;
591 strncpy( szXMLTempNameBuffer
, P_tmpdir
, sizeof(szXMLTempNameBuffer
) );
592 strncat( szXMLTempNameBuffer
, "/crxmlXXXXXX", sizeof(szXMLTempNameBuffer
) - strlen(szXMLTempNameBuffer
) - 1 );
594 strncpy( szStackTempNameBuffer
, P_tmpdir
, sizeof(szStackTempNameBuffer
) );
595 strncat( szStackTempNameBuffer
, "/crstkXXXXXX", sizeof(szStackTempNameBuffer
) - strlen(szStackTempNameBuffer
) - 1 );
597 strncpy( szChecksumTempNameBuffer
, P_tmpdir
, sizeof(szChecksumTempNameBuffer
) );
598 strncat( szChecksumTempNameBuffer
, "/crchkXXXXXX", sizeof(szChecksumTempNameBuffer
) - strlen(szChecksumTempNameBuffer
) - 1 );
600 fdxml
= mkstemp(szXMLTempNameBuffer
);
601 fdstk
= mkstemp(szStackTempNameBuffer
);
602 fdchksum
= mkstemp(szChecksumTempNameBuffer
);
604 xmlout
= fdopen( fdxml
, "w" );
605 stackout
= fdopen( fdstk
, "w" );
606 checksumout
= fdopen( fdchksum
, "w" );
608 pXMLTempName
= szXMLTempNameBuffer
;
609 pStackTempName
= szStackTempNameBuffer
;
610 pChecksumTempName
= szChecksumTempNameBuffer
;
613 if ( xmlout
&& stackout
&& checksumout
)
615 fprintf( xmlout
, "<errormail:Stack type=\"%s\">\n", STACKTYPE
);
617 fprintf( checksumout
, "<errormail:Checksums type=\"MD5\">\n" );
619 for ( iFrame
= 0; iFrame
< nFrames
; iFrame
++ )
623 fprintf( stackout
, "0x%" SAL_PRIxUINTPTR
":",
624 SAL_INT_CAST(sal_uIntPtr
, stackframes
[iFrame
]) );
626 fprintf( xmlout
, "<errormail:StackInfo pos=\"%d\" ip=\"0x%" SAL_PRIxUINTPTR
"\"",
628 SAL_INT_CAST(sal_uIntPtr
, stackframes
[iFrame
])
631 memset( &dl_info
, 0, sizeof(dl_info
) );
633 /* dladdr may fail */
634 if ( dladdr( stackframes
[iFrame
], &dl_info
) )
636 const char *dli_fname
= NULL
;
637 char *dli_fdir
= NULL
;
638 char szDirectory
[PATH_MAX
];
639 char szCanonicDirectory
[PATH_MAX
];
641 /* Don't expect that dladdr filled all members of dl_info */
643 dli_fname
= dl_info
.dli_fname
? strrchr( dl_info
.dli_fname
, '/' ) : NULL
;
647 memcpy( szDirectory
, dl_info
.dli_fname
, dli_fname
- dl_info
.dli_fname
);
648 szDirectory
[dli_fname
- dl_info
.dli_fname
] = 0;
650 dli_fdir
= realpath( szDirectory
, szCanonicDirectory
) ? szCanonicDirectory
: szDirectory
;
652 if ( *dli_fdir
&& dli_fdir
[ strlen(dli_fdir
) - 1 ] != '/' )
653 strcat( dli_fdir
, "/" );
656 dli_fname
= dl_info
.dli_fname
;
658 /* create checksum of library on stack */
661 sal_uInt8 checksum
[RTL_DIGEST_LENGTH_MD5
];
663 sal_uInt32 nBytesProcessed
= calc_md5_checksum(
664 dl_info
.dli_fname
, checksum
, sizeof(checksum
) );
665 if ( nBytesProcessed
)
669 fprintf( checksumout
, "<errormail:Checksum sum=\"0x" );
670 for ( j
= 0; j
< 16; fprintf( checksumout
, "%02X", checksum
[j
++] ) );
671 fprintf( checksumout
,
672 "\" bytes=\"%lu\" file=\"%s\"/>\n",
674 unsigned long, nBytesProcessed
),
679 if ( dl_info
.dli_fbase
&& dl_info
.dli_fname
)
682 ElfW(Off
) dynamic_offset
= dynamic_section_offset(dl_info
.dli_fname
);
683 fprintf( stackout
, " 0x%" SAL_PRI_SIZET
"x:", dynamic_offset
);
686 fprintf( stackout
, " %s + 0x%" SAL_PRI_PTRDIFFT
"x",
688 (char*)stackframes
[iFrame
] - (char*)dl_info
.dli_fbase
691 fprintf( xmlout
, " rel=\"0x%" SAL_PRI_PTRDIFFT
"x\"", (char *)stackframes
[iFrame
] - (char *)dl_info
.dli_fbase
);
693 fprintf( xmlout
, " name=\"%s\"", dli_fname
);
696 fprintf( xmlout
, " path=\"%s\"", dli_fdir
);
699 fprintf( xmlout
, " dynamicoffset=\"0x%" SAL_PRI_SIZET
"x\"", dynamic_offset
);
703 fprintf( stackout
, " ????????" );
705 if ( dl_info
.dli_sname
&& dl_info
.dli_saddr
)
707 fputs( " (", stackout
);
708 fputs_xml( dl_info
.dli_sname
, stackout
);
709 fprintf( stackout
, " + 0x%" SAL_PRI_PTRDIFFT
"x)",
710 (char*)stackframes
[iFrame
] - (char*)dl_info
.dli_saddr
);
712 fputs( " ordinal=\"", xmlout
);
713 fputs_xml( dl_info
.dli_sname
, xmlout
);
714 fprintf( xmlout
, "+0x%" SAL_PRI_PTRDIFFT
"x\"",
715 (char *)stackframes
[iFrame
] - (char *)dl_info
.dli_saddr
);
719 else /* dladdr failed */
721 fprintf( stackout
, " ????????" );
724 fprintf( stackout
, "\n" );
725 fprintf( xmlout
, "/>\n" );
729 fprintf( xmlout
, "</errormail:Stack>\n" );
730 fprintf( checksumout
, "</errormail:Checksums>\n" );
735 pStackTempName
= NULL
;
736 pChecksumTempName
= NULL
;
744 fclose( checksumout
);
746 if ( pXMLTempName
&& pChecksumTempName
&& pStackTempName
)
747 #endif /* INCLUDE_BACKTRACE */
749 rtl_uString
* crashrep_url
= NULL
;
750 rtl_uString
* crashrep_path
= NULL
;
751 rtl_String
* crashrep_path_system
= NULL
;
754 RTL_CONSTASCII_USTRINGPARAM(
755 "$BRAND_BASE_DIR/program/crashrep"),
756 OSTRING_TO_OUSTRING_CVTFLAGS
);
757 rtl_bootstrap_expandMacros(&crashrep_url
);
758 osl_getSystemPathFromFileURL(crashrep_url
, &crashrep_path
);
760 &crashrep_path_system
,
761 rtl_uString_getStr(crashrep_path
),
762 rtl_uString_getLength(crashrep_path
),
763 osl_getThreadTextEncoding(),
764 (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
765 | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR
));
766 rtl_uString_release(crashrep_url
);
767 rtl_uString_release(crashrep_path
);
768 #if defined INCLUDE_BACKTRACE && (defined LINUX || defined MACOSX)
769 snprintf( szShellCmd
, SAL_N_ELEMENTS(szShellCmd
),
770 "%s -p %d -s %d -xml %s -chksum %s -stack %s -noui%s",
771 rtl_string_getStr(crashrep_path_system
),
777 bAutoCrashReport
? " -send" : "" );
778 #elif defined INCLUDE_BACKTRACE && defined SOLARIS
779 snprintf( szShellCmd
, SAL_N_ELEMENTS(szShellCmd
),
780 "%s -p %d -s %d -xml %s -chksum %s -noui%s",
781 rtl_string_getStr(crashrep_path_system
),
786 bAutoCrashReport
? " -send" : "" );
788 snprintf( szShellCmd
, SAL_N_ELEMENTS(szShellCmd
),
789 "%s -p %d -s %d -noui%s",
790 rtl_string_getStr(crashrep_path_system
),
791 getpid(), Signal
, bAutoCrashReport
? " -send" : "" );
793 rtl_string_release(crashrep_path_system
);
796 ret
= szShellCmd
[0] == '\0' ? -1 : system( szShellCmd
);
799 unlink( pXMLTempName
);
801 if ( pStackTempName
)
802 unlink( pStackTempName
);
804 if ( pChecksumTempName
)
805 unlink( pChecksumTempName
);
809 bCrashReporterExecuted
= sal_True
;
822 #else /* defined SAL_ENABLE_CRASH_REPORT */
823 /* the utility crash_report is not build, so do the same as when
824 the option -nocrashreport is used */
825 (void) Signal
; // avoid warnings
827 #endif /* defined SAL_ENABLE_CRASH_REPORT */
830 static void PrintStack( int sig
)
832 #ifdef INCLUDE_BACKTRACE
833 void *buffer
[MAX_STACK_FRAMES
];
834 int size
= backtrace( buffer
, SAL_N_ELEMENTS(buffer
) );
837 fprintf( stderr
, "\n\nFatal exception: Signal %d\n", sig
);
839 #if defined( MACOSX ) && !defined( INCLUDE_BACKTRACE )
840 fprintf( stderr
, "Please turn on Enable Crash Reporting and\nAutomatic Display of Crashlogs in the Console application\n" );
842 #ifdef INCLUDE_BACKTRACE
845 fputs( "Stack:\n", stderr
);
846 backtrace_symbols_fd( buffer
, size
, fileno(stderr
) );
852 static oslSignalAction
CallSignalHandler(oslSignalInfo
*pInfo
)
854 oslSignalHandlerImpl
* pHandler
= SignalList
;
855 oslSignalAction Action
= osl_Signal_ActCallNextHdl
;
857 while (pHandler
!= NULL
)
859 if ((Action
= pHandler
->Handler(pHandler
->pData
, pInfo
))
860 != osl_Signal_ActCallNextHdl
)
863 pHandler
= pHandler
->pNext
;
869 void CallSystemHandler(int Signal
)
872 struct sigaction act
;
874 for (i
= 0; i
< NoSignals
; i
++)
876 if (Signals
[i
].Signal
== Signal
)
882 if ((Signals
[i
].Handler
== NULL
) ||
883 (Signals
[i
].Handler
== SIG_DFL
) ||
884 (Signals
[i
].Handler
== SIG_IGN
) ||
885 (Signals
[i
].Handler
== SIG_ERR
))
887 switch (Signals
[i
].Action
)
889 case ACT_EXIT
: /* terminate */
890 /* prevent dumping core on exit() */
894 case ACT_ABORT
: /* terminate witch core dump */
895 ReportCrash( Signal
);
896 act
.sa_handler
= SIG_DFL
;
898 sigemptyset(&(act
.sa_mask
));
899 sigaction(SIGABRT
, &act
, NULL
);
900 PrintStack( Signal
);
904 case ACT_IGNORE
: /* ignore */
907 default: /* should never happen */
912 (*Signals
[i
].Handler
)(Signal
);
916 #if defined HAVE_VALGRIND_HEADERS
917 static void DUMPCURRENTALLOCS()
919 VALGRIND_PRINTF( "=== start memcheck dump of active allocations ===\n" );
921 #if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
922 # pragma GCC diagnostic push
923 # pragma GCC diagnostic ignored "-Wunused-but-set-variable"
926 VALGRIND_DO_LEAK_CHECK
;
928 #if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
929 # pragma GCC diagnostic pop
932 VALGRIND_PRINTF( "=== end memcheck dump of active allocations ===\n" );
936 void SignalHandlerFunction(int Signal
)
939 struct sigaction act
;
941 Info
.UserSignal
= Signal
;
942 Info
.UserData
= NULL
;
950 #if ( SIGIOT != SIGABRT )
953 Info
.Signal
= osl_Signal_AccessViolation
;
957 Info
.Signal
= osl_Signal_IntegerDivideByZero
;
961 Info
.Signal
= osl_Signal_FloatDivideByZero
;
967 Info
.Signal
= osl_Signal_Terminate
;
970 #if defined HAVE_VALGRIND_HEADERS
972 if (RUNNING_ON_VALGRIND
)
974 Info
.Signal
= osl_Signal_System
;
979 Info
.Signal
= osl_Signal_System
;
983 ReportCrash( Signal
);
985 /* Portal Demo HACK !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
986 if (bDoHardKill
&& (Info
.Signal
== osl_Signal_AccessViolation
))
988 /* Portal Demo HACK !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
991 switch (CallSignalHandler(&Info
))
993 case osl_Signal_ActCallNextHdl
:
994 CallSystemHandler(Signal
);
997 case osl_Signal_ActAbortApp
:
998 ReportCrash( Signal
);
999 act
.sa_handler
= SIG_DFL
;
1001 sigemptyset(&(act
.sa_mask
));
1002 sigaction(SIGABRT
, &act
, NULL
);
1003 PrintStack( Signal
);
1007 case osl_Signal_ActKillApp
:
1008 /* prevent dumping core on exit() */
1016 oslSignalHandler SAL_CALL
osl_addSignalHandler(oslSignalHandlerFunction Handler
, void* pData
)
1018 oslSignalHandlerImpl
* pHandler
;
1020 OSL_ASSERT(Handler
!= NULL
);
1027 bInitSignal
= InitSignal();
1029 pHandler
= (oslSignalHandlerImpl
*) calloc(1, sizeof(oslSignalHandlerImpl
));
1031 if (pHandler
!= NULL
)
1033 pHandler
->Handler
= Handler
;
1034 pHandler
->pData
= pData
;
1036 osl_acquireMutex(SignalListMutex
);
1038 pHandler
->pNext
= SignalList
;
1039 SignalList
= pHandler
;
1041 osl_releaseMutex(SignalListMutex
);
1049 sal_Bool SAL_CALL
osl_removeSignalHandler(oslSignalHandler Handler
)
1051 oslSignalHandlerImpl
*pHandler
, *pPrevious
= NULL
;
1053 OSL_ASSERT(Handler
!= NULL
);
1056 bInitSignal
= InitSignal();
1058 osl_acquireMutex(SignalListMutex
);
1060 pHandler
= SignalList
;
1062 while (pHandler
!= NULL
)
1064 if (pHandler
== Handler
)
1067 pPrevious
->pNext
= pHandler
->pNext
;
1069 SignalList
= pHandler
->pNext
;
1071 osl_releaseMutex(SignalListMutex
);
1073 if (SignalList
== NULL
)
1074 bInitSignal
= DeInitSignal();
1081 pPrevious
= pHandler
;
1082 pHandler
= pHandler
->pNext
;
1085 osl_releaseMutex(SignalListMutex
);
1090 oslSignalAction SAL_CALL
osl_raiseSignal(sal_Int32 UserSignal
, void* UserData
)
1093 oslSignalAction Action
;
1096 bInitSignal
= InitSignal();
1098 osl_acquireMutex(SignalListMutex
);
1100 Info
.Signal
= osl_Signal_User
;
1101 Info
.UserSignal
= UserSignal
;
1102 Info
.UserData
= UserData
;
1104 Action
= CallSignalHandler(&Info
);
1106 osl_releaseMutex(SignalListMutex
);
1111 sal_Bool SAL_CALL
osl_setErrorReporting( sal_Bool bEnable
)
1113 sal_Bool bOld
= bErrorReportingEnabled
;
1114 bErrorReportingEnabled
= bEnable
;
1119 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */