1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: signal.c,v $
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 ************************************************************************/
35 #define MAX_STACK_FRAMES 256
40 #include "backtrace.h"
41 #define INCLUDE_BACKTRACE
42 #define STACKTYPE "MacOsX_X86"
50 #define INCLUDE_BACKTRACE
51 #define STACKTYPE "Linux"
56 #include "backtrace.h"
57 #define INCLUDE_BACKTRACE
60 #define STACKTYPE "Solaris_Sparc"
61 #elif defined( INTEL )
62 #define STACKTYPE "Solaris_X86"
64 #define STACKTYPE "Solaris_Unknown"
67 #endif /* defined SOLARIS */
69 #include <osl/diagnose.h>
70 #include <osl/mutex.h>
71 #include <osl/signal.h>
72 #include <osl/process.h>
73 #include <osl/thread.h>
74 #include <rtl/bootstrap.h>
75 #include <rtl/digest.h>
77 #include "file_path_helper.h"
85 #define MAX_PATH_LEN 2048
87 typedef struct _oslSignalHandlerImpl
89 oslSignalHandlerFunction Handler
;
91 struct _oslSignalHandlerImpl
* pNext
;
92 } oslSignalHandlerImpl
;
94 static struct SignalAction
101 { SIGHUP
, ACT_IGNORE
, NULL
}, /* hangup */
102 { SIGINT
, ACT_EXIT
, NULL
}, /* interrupt (rubout) */
103 { SIGQUIT
, ACT_EXIT
, NULL
}, /* quit (ASCII FS) */
104 { SIGILL
, ACT_SYSTEM
, NULL
}, /* illegal instruction (not reset when caught) */
105 /* changed from ACT_ABOUT to ACT_SYSTEM to try and get collector to run*/
106 { SIGTRAP
, ACT_ABORT
, NULL
}, /* trace trap (not reset when caught) */
107 #if ( SIGIOT != SIGABRT )
108 { SIGIOT
, ACT_ABORT
, NULL
}, /* IOT instruction */
110 { SIGABRT
, ACT_ABORT
, NULL
}, /* used by abort, replace SIGIOT in the future */
112 { SIGEMT
, ACT_SYSTEM
, NULL
}, /* EMT instruction */
113 /* changed from ACT_ABORT to ACT_SYSTEM to remove handler*/
114 /* SIGEMT may also be used by the profiler - so it is probably not a good
115 plan to have the new handler use this signal*/
117 { SIGFPE
, ACT_ABORT
, NULL
}, /* floating point exception */
118 { SIGKILL
, ACT_SYSTEM
, NULL
}, /* kill (cannot be caught or ignored) */
119 { SIGBUS
, ACT_ABORT
, NULL
}, /* bus error */
120 { SIGSEGV
, ACT_ABORT
, NULL
}, /* segmentation violation */
122 { SIGSYS
, ACT_ABORT
, NULL
}, /* bad argument to system call */
124 { SIGPIPE
, ACT_HIDE
, NULL
}, /* write on a pipe with no one to read it */
125 { SIGALRM
, ACT_EXIT
, NULL
}, /* alarm clock */
126 { SIGTERM
, ACT_EXIT
, NULL
}, /* software termination signal from kill */
127 { SIGUSR1
, ACT_SYSTEM
, NULL
}, /* user defined signal 1 */
128 { SIGUSR2
, ACT_SYSTEM
, NULL
}, /* user defined signal 2 */
129 { SIGCHLD
, ACT_SYSTEM
, NULL
}, /* child status change */
131 { SIGPWR
, ACT_IGNORE
, NULL
}, /* power-fail restart */
133 { SIGWINCH
, ACT_IGNORE
, NULL
}, /* window size change */
134 { SIGURG
, ACT_EXIT
, NULL
}, /* urgent socket condition */
136 { SIGPOLL
, ACT_EXIT
, NULL
}, /* pollable event occured */
138 { SIGSTOP
, ACT_SYSTEM
, NULL
}, /* stop (cannot be caught or ignored) */
139 { SIGTSTP
, ACT_SYSTEM
, NULL
}, /* user stop requested from tty */
140 { SIGCONT
, ACT_SYSTEM
, NULL
}, /* stopped process has been continued */
141 { SIGTTIN
, ACT_SYSTEM
, NULL
}, /* background tty read attempted */
142 { SIGTTOU
, ACT_SYSTEM
, NULL
}, /* background tty write attempted */
143 { SIGVTALRM
, ACT_EXIT
, NULL
}, /* virtual timer expired */
144 { SIGPROF
, ACT_SYSTEM
, NULL
}, /* profiling timer expired */
145 /*Change from ACT_EXIT to ACT_SYSTEM for SIGPROF is so that profiling signals do
146 not get taken by the new handler - the new handler does not pass on context
147 information which causes 'collect' to crash. This is a way of avoiding
148 what looks like a bug in the new handler*/
149 { SIGXCPU
, ACT_ABORT
, NULL
}, /* exceeded cpu limit */
150 { SIGXFSZ
, ACT_ABORT
, NULL
} /* exceeded file size limit */
152 const int NoSignals
= sizeof(Signals
) / sizeof(struct SignalAction
);
154 static sal_Bool bErrorReportingEnabled
= sal_True
;
155 static sal_Bool bInitSignal
= sal_False
;
156 static oslMutex SignalListMutex
;
157 static oslSignalHandlerImpl
* SignalList
;
158 static sal_Bool bDoHardKill
= sal_False
;
159 static sal_Bool bSetSEGVHandler
= sal_False
;
160 static sal_Bool bSetWINCHHandler
= sal_False
;
161 static sal_Bool bSetILLHandler
= sal_False
;
163 static void SignalHandlerFunction(int);
165 static void getExecutableName_Impl (rtl_String
** ppstrProgName
)
167 rtl_uString
* ustrProgFile
= 0;
168 osl_getExecutableFile (&ustrProgFile
);
171 rtl_uString
* ustrProgName
= 0;
172 osl_systemPathGetFileNameOrLastDirectoryPart (ustrProgFile
, &ustrProgName
);
173 if (ustrProgName
!= 0)
177 rtl_uString_getStr (ustrProgName
), rtl_uString_getLength (ustrProgName
),
178 osl_getThreadTextEncoding(),
179 OUSTRING_TO_OSTRING_CVTFLAGS
);
180 rtl_uString_release (ustrProgName
);
182 rtl_uString_release (ustrProgFile
);
186 static sal_Bool
is_soffice_Impl (void)
189 rtl_String
* strProgName
= 0;
191 getExecutableName_Impl (&strProgName
);
194 idx
= rtl_str_indexOfStr (rtl_string_getStr (strProgName
), "soffice");
195 rtl_string_release (strProgName
);
200 static sal_Bool
InitSignal()
203 struct sigaction act
;
204 struct sigaction oact
;
206 if (is_soffice_Impl())
210 rtl_uString
*ustrCommandArg
= 0;
212 argc
= osl_getCommandArgCount();
213 for ( argi
= 0; argi
< argc
; argi
++ )
215 if (osl_Process_E_None
== osl_getCommandArg (argi
, &ustrCommandArg
))
217 if (0 == rtl_ustr_ascii_compare (rtl_uString_getStr (ustrCommandArg
), "-bean"))
219 bDoHardKill
= sal_True
;
226 rtl_uString_release (ustrCommandArg
);
230 // WORKAROUND FOR SEGV HANDLER CONFLICT
232 // the java jit needs SIGSEGV for proper work
233 // and we need SIGSEGV for the office crashguard
235 // TEMPORARY SOLUTION:
236 // the office sets the signal handler during startup
237 // java can than overwrite it, if needed
238 bSetSEGVHandler
= sal_True
;
240 // WORKAROUND FOR WINCH HANDLER (SEE ABOVE)
241 bSetWINCHHandler
= sal_True
;
243 // WORKAROUND FOR ILLEGAL INSTRUCTION HANDLER (SEE ABOVE)
244 bSetILLHandler
= sal_True
;
247 SignalListMutex
= osl_createMutex();
249 act
.sa_handler
= SignalHandlerFunction
;
250 act
.sa_flags
= SA_RESTART
;
252 sigfillset(&(act
.sa_mask
));
254 /* Initialize the rest of the signals */
255 for (i
= 0; i
< NoSignals
; i
++)
257 /* hack: stomcatd is attaching JavaVM wich dont work with an sigaction(SEGV) */
258 if ((bSetSEGVHandler
|| Signals
[i
].Signal
!= SIGSEGV
)
259 && (bSetWINCHHandler
|| Signals
[i
].Signal
!= SIGWINCH
)
260 && (bSetILLHandler
|| Signals
[i
].Signal
!= SIGILL
))
262 if (Signals
[i
].Action
!= ACT_SYSTEM
)
264 if (Signals
[i
].Action
== ACT_HIDE
)
266 struct sigaction ign
;
268 ign
.sa_handler
= SIG_IGN
;
270 sigemptyset(&ign
.sa_mask
);
272 if (sigaction(Signals
[i
].Signal
, &ign
, &oact
) == 0)
273 Signals
[i
].Handler
= oact
.sa_handler
;
275 Signals
[i
].Handler
= SIG_DFL
;
278 if (sigaction(Signals
[i
].Signal
, &act
, &oact
) == 0)
279 Signals
[i
].Handler
= oact
.sa_handler
;
281 Signals
[i
].Handler
= SIG_DFL
;
289 static sal_Bool
DeInitSignal()
292 struct sigaction act
;
295 sigemptyset(&(act
.sa_mask
));
297 /* Initialize the rest of the signals */
298 for (i
= NoSignals
- 1; i
>= 0; i
--)
299 if (Signals
[i
].Action
!= ACT_SYSTEM
)
301 act
.sa_handler
= Signals
[i
].Handler
;
303 sigaction(Signals
[i
].Signal
, &act
, NULL
);
306 osl_destroyMutex(SignalListMutex
);
311 #if defined (SAL_ENABLE_CRASH_REPORT) && defined(INCLUDE_BACKTRACE)
313 /*****************************************************************************/
314 /* Generate MD5 checksum */
315 /*****************************************************************************/
317 static sal_uInt32
calc_md5_checksum( const char *filename
, sal_uInt8
*pChecksum
, sal_uInt32 nChecksumLen
)
319 sal_uInt32 nBytesProcessed
= 0;
321 FILE *fp
= fopen( filename
, "r" );
325 rtlDigest digest
= rtl_digest_createMD5();
330 sal_uInt8 buffer
[4096];
331 rtlDigestError error
= rtl_Digest_E_None
;
333 while ( rtl_Digest_E_None
== error
&&
334 0 != (nBytesRead
= fread( buffer
, 1, sizeof(buffer
), fp
)) )
336 error
= rtl_digest_updateMD5( digest
, buffer
, nBytesRead
);
337 nBytesProcessed
+= nBytesRead
;
340 if ( rtl_Digest_E_None
== error
)
342 error
= rtl_digest_getMD5( digest
, pChecksum
, nChecksumLen
);
345 if ( rtl_Digest_E_None
!= error
)
348 rtl_digest_destroyMD5( digest
);
354 return nBytesProcessed
;
357 /*****************************************************************************/
358 /* Call crash reporter */
359 /*****************************************************************************/
361 /* Helper function to encode and write a string to a stream */
363 static int fputs_xml( const char *string
, FILE *stream
)
367 while ( result
>= 0 && *string
)
372 result
= fputs( "&", stream
);
375 result
= fputs( "<", stream
);
378 result
= fputs( ">", stream
);
381 result
= fputc( *string
, stream
);
392 /* Create intermediate files and run crash reporter */
394 #define REPORTENV_PARAM "-crashreportenv:"
396 #if defined SAL_ENABLE_CRASH_REPORT && defined INCLUDE_BACKTRACE && \
406 callback(struct dl_phdr_info
*info
, size_t size
, void *data
)
408 const ElfW(Phdr
) *pDynamic
= NULL
;
410 if (size
== sizeof(struct dl_phdr_info
))
413 for (i
= 0; i
< info
->dlpi_phnum
; ++i
)
415 if (info
->dlpi_phdr
[i
].p_type
== PT_DYNAMIC
)
417 pDynamic
= &(info
->dlpi_phdr
[i
]);
428 const char *dsoname
= info
->dlpi_name
;
430 dynamic_entry
* entry
= (dynamic_entry
*)data
;
432 if (strcmp(dsoname
, "") == 0)
434 snprintf(buffer
, sizeof(buffer
), "/proc/%d/exe", getpid());
435 if ((len
= readlink(buffer
, exe
, PATH_MAX
)) != -1)
442 if (strcmp(dsoname
, entry
->name
) == 0)
444 entry
->offset
= pDynamic
->p_offset
;
451 /* Get the location of the .dynamic section offset for the given elf file.
452 * i.e. same as the "Offset" value shown for DYNAMIC from readelf -l foo
454 * We want to know this value so that if the binaries have been modifed
455 * by prelink then we can still process the call stack on server side
456 * by comparing this value to that of an "un-prelinked but known to be
457 * otherwise equivalent" version of those binaries and adjust the call
458 * stack addresses by the differences between .dynamic addresses so as
459 * to be able to map the prelinked addresses back to the unprelinked
465 dynamic_section_offset(const char *name
)
472 dl_iterate_phdr(callback
, &entry
);
478 static int ReportCrash( int Signal
)
480 #ifdef SAL_ENABLE_CRASH_REPORT
481 static sal_Bool bCrashReporterExecuted
= sal_False
;
482 sal_Bool bAutoCrashReport
= sal_False
;
486 rtl_uString
*ustrCommandArg
= NULL
;
488 if ( !bErrorReportingEnabled
)
491 argc
= osl_getCommandArgCount();
493 for ( argi
= 0; argi
< argc
; argi
++ )
495 if ( osl_Process_E_None
== osl_getCommandArg( argi
, &ustrCommandArg
) )
497 if ( 0 == rtl_ustr_ascii_compare( rtl_uString_getStr( ustrCommandArg
), "-nocrashreport" ) )
499 rtl_uString_release( ustrCommandArg
);
502 else if ( 0 == rtl_ustr_ascii_compare( rtl_uString_getStr( ustrCommandArg
), "-autocrashreport" ) )
504 bAutoCrashReport
= sal_True
;
506 else if ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength(
507 rtl_uString_getStr( ustrCommandArg
), rtl_uString_getLength( ustrCommandArg
),
508 REPORTENV_PARAM
, strlen(REPORTENV_PARAM
) )
511 rtl_uString
*ustrEnvironment
= NULL
;
512 rtl_String
*strEnv
= NULL
;
514 rtl_uString_newFromStr( &ustrEnvironment
, rtl_uString_getStr( ustrCommandArg
) + strlen(REPORTENV_PARAM
) );
516 if ( ustrEnvironment
)
520 rtl_uString_getStr( ustrEnvironment
), rtl_uString_getLength( ustrEnvironment
),
521 osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS
526 putenv( rtl_string_getStr( strEnv
) );
527 rtl_string_release( strEnv
);
530 rtl_uString_release( ustrEnvironment
);
538 if ( ustrCommandArg
)
539 rtl_uString_release( ustrCommandArg
);
541 if ( !bCrashReporterExecuted
)
544 /* struct sigaction act; */
546 for (i
= 0; i
< NoSignals
; i
++)
548 if (Signals
[i
].Signal
== Signal
&& Signals
[i
].Action
== ACT_ABORT
)
551 char szShellCmd
[512];
552 char *pXMLTempName
= NULL
;
553 char *pStackTempName
= NULL
;
554 char *pChecksumTempName
= NULL
;
556 #ifdef INCLUDE_BACKTRACE
557 char szXMLTempNameBuffer
[L_tmpnam
];
558 char szChecksumTempNameBuffer
[L_tmpnam
];
559 char szStackTempNameBuffer
[L_tmpnam
];
561 void *stackframes
[MAX_STACK_FRAMES
];
563 int nFrames
= backtrace( stackframes
, sizeof(stackframes
)/sizeof(stackframes
[0]));
565 FILE *xmlout
= NULL
, *stackout
= NULL
, *checksumout
= NULL
;
566 int fdxml
, fdstk
, fdchksum
;
568 strncpy( szXMLTempNameBuffer
, P_tmpdir
, sizeof(szXMLTempNameBuffer
) );
569 strncat( szXMLTempNameBuffer
, "/crxmlXXXXXX", sizeof(szXMLTempNameBuffer
) );
571 strncpy( szStackTempNameBuffer
, P_tmpdir
, sizeof(szStackTempNameBuffer
) );
572 strncat( szStackTempNameBuffer
, "/crstkXXXXXX", sizeof(szStackTempNameBuffer
) );
574 strncpy( szChecksumTempNameBuffer
, P_tmpdir
, sizeof(szChecksumTempNameBuffer
) );
575 strncat( szChecksumTempNameBuffer
, "/crchkXXXXXX", sizeof(szChecksumTempNameBuffer
) );
577 fdxml
= mkstemp(szXMLTempNameBuffer
);
578 fdstk
= mkstemp(szStackTempNameBuffer
);
579 fdchksum
= mkstemp(szChecksumTempNameBuffer
);
581 xmlout
= fdopen( fdxml
, "w" );
582 stackout
= fdopen( fdstk
, "w" );
583 checksumout
= fdopen( fdchksum
, "w" );
585 pXMLTempName
= szXMLTempNameBuffer
;
586 pStackTempName
= szStackTempNameBuffer
;
587 pChecksumTempName
= szChecksumTempNameBuffer
;
590 if ( xmlout
&& stackout
&& checksumout
)
592 fprintf( xmlout
, "<errormail:Stack type=\"%s\">\n", STACKTYPE
);
594 fprintf( checksumout
, "<errormail:Checksums type=\"MD5\">\n" );
596 for ( iFrame
= 0; iFrame
< nFrames
; iFrame
++ )
600 fprintf( stackout
, "0x%" SAL_PRIxUINTPTR
":",
601 SAL_INT_CAST(sal_uIntPtr
, stackframes
[iFrame
]) );
603 fprintf( xmlout
, "<errormail:StackInfo pos=\"%d\" ip=\"0x%" SAL_PRIxUINTPTR
"\"",
605 SAL_INT_CAST(sal_uIntPtr
, stackframes
[iFrame
])
608 memset( &dl_info
, 0, sizeof(dl_info
) );
610 /* dladdr may fail */
611 if ( dladdr( stackframes
[iFrame
], &dl_info
) )
613 const char *dli_fname
= NULL
;
614 char *dli_fdir
= NULL
;
615 char szDirectory
[PATH_MAX
];
616 char szCanonicDirectory
[PATH_MAX
];
618 /* Don't expect that dladdr filled all members of dl_info */
620 dli_fname
= dl_info
.dli_fname
? strrchr( dl_info
.dli_fname
, '/' ) : NULL
;
624 memcpy( szDirectory
, dl_info
.dli_fname
, dli_fname
- dl_info
.dli_fname
);
625 szDirectory
[dli_fname
- dl_info
.dli_fname
] = 0;
627 dli_fdir
= realpath( szDirectory
, szCanonicDirectory
) ? szCanonicDirectory
: szDirectory
;
629 if ( *dli_fdir
&& dli_fdir
[ strlen(dli_fdir
) - 1 ] != '/' )
630 strcat( dli_fdir
, "/" );
633 dli_fname
= dl_info
.dli_fname
;
635 /* create checksum of library on stack */
638 sal_uInt8 checksum
[RTL_DIGEST_LENGTH_MD5
];
640 sal_uInt32 nBytesProcessed
= calc_md5_checksum(
641 dl_info
.dli_fname
, checksum
, sizeof(checksum
) );
642 if ( nBytesProcessed
)
646 fprintf( checksumout
, "<errormail:Checksum sum=\"0x" );
647 for ( j
= 0; j
< 16; fprintf( checksumout
, "%02X", checksum
[j
++] ) );
648 fprintf( checksumout
,
649 "\" bytes=\"%lu\" file=\"%s\"/>\n",
651 unsigned long, nBytesProcessed
),
656 if ( dl_info
.dli_fbase
&& dl_info
.dli_fname
)
659 ElfW(Off
) dynamic_offset
= dynamic_section_offset(dl_info
.dli_fname
);
660 fprintf( stackout
, " 0x%" SAL_PRI_SIZET
"x:", dynamic_offset
);
663 fprintf( stackout
, " %s + 0x%" SAL_PRI_PTRDIFFT
"x",
665 (char*)stackframes
[iFrame
] - (char*)dl_info
.dli_fbase
668 fprintf( xmlout
, " rel=\"0x%" SAL_PRI_PTRDIFFT
"x\"", (char *)stackframes
[iFrame
] - (char *)dl_info
.dli_fbase
);
670 fprintf( xmlout
, " name=\"%s\"", dli_fname
);
673 fprintf( xmlout
, " path=\"%s\"", dli_fdir
);
676 fprintf( xmlout
, " dynamicoffset=\"0x%" SAL_PRI_SIZET
"x\"", dynamic_offset
);
680 fprintf( stackout
, " ????????" );
682 if ( dl_info
.dli_sname
&& dl_info
.dli_saddr
)
684 fputs( " (", stackout
);
685 fputs_xml( dl_info
.dli_sname
, stackout
);
686 fprintf( stackout
, " + 0x%" SAL_PRI_PTRDIFFT
"x)",
687 (char*)stackframes
[iFrame
] - (char*)dl_info
.dli_saddr
);
689 fputs( " ordinal=\"", xmlout
);
690 fputs_xml( dl_info
.dli_sname
, xmlout
);
691 fprintf( xmlout
, "+0x%" SAL_PRI_PTRDIFFT
"x\"",
692 (char *)stackframes
[iFrame
] - (char *)dl_info
.dli_saddr
);
696 else /* dladdr failed */
698 fprintf( stackout
, " ????????" );
701 fprintf( stackout
, "\n" );
702 fprintf( xmlout
, "/>\n" );
706 fprintf( xmlout
, "</errormail:Stack>\n" );
707 fprintf( checksumout
, "</errormail:Checksums>\n" );
712 pStackTempName
= NULL
;
713 pChecksumTempName
= NULL
;
721 fclose( checksumout
);
724 if ( pXMLTempName
&& pChecksumTempName
&& pStackTempName
)
725 snprintf( szShellCmd
, sizeof(szShellCmd
)/sizeof(szShellCmd
[0]),
726 "crash_report -p %d -s %d -xml %s -chksum %s -stack %s%s",
732 bAutoCrashReport
? " -noui -send" : " -noui" );
733 #elif defined( MACOSX )
734 if ( pXMLTempName
&& pChecksumTempName
&& pStackTempName
)
736 rtl_uString
*crashrep_url
= NULL
;
737 rtl_uString
*crashrep_path
= NULL
;
738 rtl_String
*crashrep_path_system
= NULL
;
740 rtl_string2UString( &crashrep_url
, RTL_CONSTASCII_USTRINGPARAM("$BRAND_BASE_DIR/program/crash_report.bin"), OSTRING_TO_OUSTRING_CVTFLAGS
);
741 rtl_bootstrap_expandMacros( &crashrep_url
);
742 osl_getSystemPathFromFileURL( crashrep_url
, &crashrep_path
);
744 &crashrep_path_system
,
745 rtl_uString_getStr( crashrep_path
),
746 rtl_uString_getLength( crashrep_path
),
747 osl_getThreadTextEncoding(),
748 RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
| RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR
);
750 rtl_uString_release( crashrep_url
);
751 rtl_uString_release( crashrep_path
);
753 snprintf( szShellCmd
, sizeof(szShellCmd
)/sizeof(szShellCmd
[0]),
754 "%s -p %d -s %d -xml %s -chksum %s -stack %s%s",
755 rtl_string_getStr( crashrep_path_system
),
761 bAutoCrashReport
? " -noui -send" : " -noui" );
763 rtl_string_release( crashrep_path_system
);
765 printf( "%s\n", szShellCmd
);
767 #elif defined ( SOLARIS )
768 if ( pXMLTempName
&& pChecksumTempName
)
769 snprintf( szShellCmd
, sizeof(szShellCmd
)/sizeof(szShellCmd
[0]),
770 "crash_report -p %d -s %d -xml %s -chksum %s%s",
775 bAutoCrashReport
? " -noui -send" : " -noui" );
778 #else /* defined INCLUDE BACKTRACE */
779 snprintf( szShellCmd
, sizeof(szShellCmd
)/sizeof(szShellCmd
[0]),
780 "crash_report -p %d -s %d%s", getpid(), Signal
, bAutoCrashReport
? " -noui -send" : " -noui" );
781 #endif /* defined INCLUDE BACKTRACE */
784 ret
= system( szShellCmd
);
787 unlink( pXMLTempName
);
789 if ( pStackTempName
)
790 unlink( pStackTempName
);
792 if ( pChecksumTempName
)
793 unlink( pChecksumTempName
);
797 bCrashReporterExecuted
= sal_True
;
810 #else /* defined SAL_ENABLE_CRASH_REPORT */
811 /* the utility crash_report is not build, so do the same as when
812 the option -nocrashreport is used */
813 (void) Signal
; // avoid warnings
815 #endif /* defined SAL_ENABLE_CRASH_REPORT */
818 static void PrintStack( int sig
)
820 #if ! defined(MACOSX) || defined(INCLUDE_BACKTRACE)
821 void *buffer
[MAX_STACK_FRAMES
];
822 int size
= backtrace( buffer
, sizeof(buffer
) / sizeof(buffer
[0]) );
825 fprintf( stderr
, "\n\nFatal exception: Signal %d\n", sig
);
827 #if defined(MACOSX) && ! defined(INCLUDE_BACKTRACE)
828 fprintf( stderr
, "Please turn on Enable Crash Reporting and\nAutomatic Display of Crashlogs in the Console application\n" );
832 fputs( "Stack:\n", stderr
);
833 backtrace_symbols_fd( buffer
, size
, fileno(stderr
) );
838 static oslSignalAction
CallSignalHandler(oslSignalInfo
*pInfo
)
840 oslSignalHandlerImpl
* pHandler
= SignalList
;
841 oslSignalAction Action
= osl_Signal_ActCallNextHdl
;
843 while (pHandler
!= NULL
)
845 if ((Action
= pHandler
->Handler(pHandler
->pData
, pInfo
))
846 != osl_Signal_ActCallNextHdl
)
849 pHandler
= pHandler
->pNext
;
855 void CallSystemHandler(int Signal
)
858 struct sigaction act
;
860 for (i
= 0; i
< NoSignals
; i
++)
862 if (Signals
[i
].Signal
== Signal
)
868 if ((Signals
[i
].Handler
== NULL
) ||
869 (Signals
[i
].Handler
== SIG_DFL
) ||
870 (Signals
[i
].Handler
== SIG_IGN
) ||
871 (Signals
[i
].Handler
== SIG_ERR
))
873 switch (Signals
[i
].Action
)
875 case ACT_EXIT
: /* terminate */
876 /* prevent dumping core on exit() */
880 case ACT_ABORT
: /* terminate witch core dump */
881 ReportCrash( Signal
);
882 act
.sa_handler
= SIG_DFL
;
884 sigemptyset(&(act
.sa_mask
));
885 sigaction(SIGABRT
, &act
, NULL
);
886 PrintStack( Signal
);
890 case ACT_IGNORE
: /* ignore */
893 default: /* should never happen */
898 (*Signals
[i
].Handler
)(Signal
);
903 /*****************************************************************************/
904 /* SignalHandlerFunction */
905 /*****************************************************************************/
906 void SignalHandlerFunction(int Signal
)
909 struct sigaction act
;
911 Info
.UserSignal
= Signal
;
912 Info
.UserData
= NULL
;
920 #if ( SIGIOT != SIGABRT )
923 Info
.Signal
= osl_Signal_AccessViolation
;
927 Info
.Signal
= osl_Signal_IntegerDivideByZero
;
931 Info
.Signal
= osl_Signal_FloatDivideByZero
;
938 Info
.Signal
= osl_Signal_Terminate
;
942 Info
.Signal
= osl_Signal_System
;
946 ReportCrash( Signal
);
948 /* Portal Demo HACK !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
949 if (bDoHardKill
&& (Info
.Signal
== osl_Signal_AccessViolation
))
951 /* Portal Demo HACK !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
954 switch (CallSignalHandler(&Info
))
956 case osl_Signal_ActCallNextHdl
:
957 CallSystemHandler(Signal
);
960 case osl_Signal_ActAbortApp
:
961 ReportCrash( Signal
);
962 act
.sa_handler
= SIG_DFL
;
964 sigemptyset(&(act
.sa_mask
));
965 sigaction(SIGABRT
, &act
, NULL
);
966 PrintStack( Signal
);
970 case osl_Signal_ActKillApp
:
971 /* prevent dumping core on exit() */
979 /*****************************************************************************/
980 /* osl_addSignalHandler */
981 /*****************************************************************************/
982 oslSignalHandler SAL_CALL
osl_addSignalHandler(oslSignalHandlerFunction Handler
, void* pData
)
984 oslSignalHandlerImpl
* pHandler
;
986 OSL_ASSERT(Handler
!= NULL
);
993 bInitSignal
= InitSignal();
995 pHandler
= (oslSignalHandlerImpl
*) calloc(1, sizeof(oslSignalHandlerImpl
));
997 if (pHandler
!= NULL
)
999 pHandler
->Handler
= Handler
;
1000 pHandler
->pData
= pData
;
1002 osl_acquireMutex(SignalListMutex
);
1004 pHandler
->pNext
= SignalList
;
1005 SignalList
= pHandler
;
1007 osl_releaseMutex(SignalListMutex
);
1015 /*****************************************************************************/
1016 /* osl_removeSignalHandler */
1017 /*****************************************************************************/
1018 sal_Bool SAL_CALL
osl_removeSignalHandler(oslSignalHandler Handler
)
1020 oslSignalHandlerImpl
*pHandler
, *pPrevious
= NULL
;
1022 OSL_ASSERT(Handler
!= NULL
);
1025 bInitSignal
= InitSignal();
1027 osl_acquireMutex(SignalListMutex
);
1029 pHandler
= SignalList
;
1031 while (pHandler
!= NULL
)
1033 if (pHandler
== Handler
)
1036 pPrevious
->pNext
= pHandler
->pNext
;
1038 SignalList
= pHandler
->pNext
;
1040 osl_releaseMutex(SignalListMutex
);
1042 if (SignalList
== NULL
)
1043 bInitSignal
= DeInitSignal();
1050 pPrevious
= pHandler
;
1051 pHandler
= pHandler
->pNext
;
1054 osl_releaseMutex(SignalListMutex
);
1059 /*****************************************************************************/
1060 /* osl_raiseSignal */
1061 /*****************************************************************************/
1062 oslSignalAction SAL_CALL
osl_raiseSignal(sal_Int32 UserSignal
, void* UserData
)
1065 oslSignalAction Action
;
1068 bInitSignal
= InitSignal();
1070 osl_acquireMutex(SignalListMutex
);
1072 Info
.Signal
= osl_Signal_User
;
1073 Info
.UserSignal
= UserSignal
;
1074 Info
.UserData
= UserData
;
1076 Action
= CallSignalHandler(&Info
);
1078 osl_releaseMutex(SignalListMutex
);
1083 /*****************************************************************************/
1084 /* osl_setErrorReporting */
1085 /*****************************************************************************/
1086 sal_Bool SAL_CALL
osl_setErrorReporting( sal_Bool bEnable
)
1088 sal_Bool bOld
= bErrorReportingEnabled
;
1089 bErrorReportingEnabled
= bEnable
;