merge the formfield patch from ooo-build
[ooovba.git] / sal / osl / unx / signal.c
blob38d509f963e88a549fa59554ca8c03366110798f
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: signal.c,v $
10 * $Revision: 1.37 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
32 /* system headers */
33 #include "system.h"
35 #define MAX_STACK_FRAMES 256
37 #if defined( MACOSX )
39 #if defined( INTEL )
40 #include "backtrace.h"
41 #define INCLUDE_BACKTRACE
42 #define STACKTYPE "MacOsX_X86"
43 #endif /* INTEL */
45 #endif /* MACOSX */
47 #ifdef LINUX
48 #include <execinfo.h>
49 #include <link.h>
50 #define INCLUDE_BACKTRACE
51 #define STACKTYPE "Linux"
52 #endif
54 #ifdef SOLARIS
56 #include "backtrace.h"
57 #define INCLUDE_BACKTRACE
59 #if defined( SPARC )
60 #define STACKTYPE "Solaris_Sparc"
61 #elif defined( INTEL )
62 #define STACKTYPE "Solaris_X86"
63 #else
64 #define STACKTYPE "Solaris_Unknown"
65 #endif
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"
79 #define ACT_IGNORE 1
80 #define ACT_ABORT 2
81 #define ACT_EXIT 3
82 #define ACT_SYSTEM 4
83 #define ACT_HIDE 5
85 #define MAX_PATH_LEN 2048
87 typedef struct _oslSignalHandlerImpl
89 oslSignalHandlerFunction Handler;
90 void* pData;
91 struct _oslSignalHandlerImpl* pNext;
92 } oslSignalHandlerImpl;
94 static struct SignalAction
96 int Signal;
97 int Action;
98 void (*Handler)(int);
99 } Signals[] =
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 */
109 #endif
110 { SIGABRT, ACT_ABORT, NULL }, /* used by abort, replace SIGIOT in the future */
111 #ifdef SIGEMT
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*/
116 #endif
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 */
121 #ifdef SIGSYS
122 { SIGSYS, ACT_ABORT, NULL }, /* bad argument to system call */
123 #endif
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 */
130 #ifdef SIGPWR
131 { SIGPWR, ACT_IGNORE, NULL }, /* power-fail restart */
132 #endif
133 { SIGWINCH, ACT_IGNORE, NULL }, /* window size change */
134 { SIGURG, ACT_EXIT, NULL }, /* urgent socket condition */
135 #ifdef SIGPOLL
136 { SIGPOLL, ACT_EXIT, NULL }, /* pollable event occured */
137 #endif
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);
169 if (ustrProgFile)
171 rtl_uString * ustrProgName = 0;
172 osl_systemPathGetFileNameOrLastDirectoryPart (ustrProgFile, &ustrProgName);
173 if (ustrProgName != 0)
175 rtl_uString2String (
176 ppstrProgName,
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)
188 sal_Int32 idx = -1;
189 rtl_String * strProgName = 0;
191 getExecutableName_Impl (&strProgName);
192 if (strProgName)
194 idx = rtl_str_indexOfStr (rtl_string_getStr (strProgName), "soffice");
195 rtl_string_release (strProgName);
197 return (idx != -1);
200 static sal_Bool InitSignal()
202 int i;
203 struct sigaction act;
204 struct sigaction oact;
206 if (is_soffice_Impl())
208 sal_uInt32 argi;
209 sal_uInt32 argc;
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;
220 break;
224 if (ustrCommandArg)
226 rtl_uString_release (ustrCommandArg);
227 ustrCommandArg = 0;
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;
269 ign.sa_flags = 0;
270 sigemptyset(&ign.sa_mask);
272 if (sigaction(Signals[i].Signal, &ign, &oact) == 0)
273 Signals[i].Handler = oact.sa_handler;
274 else
275 Signals[i].Handler = SIG_DFL;
277 else
278 if (sigaction(Signals[i].Signal, &act, &oact) == 0)
279 Signals[i].Handler = oact.sa_handler;
280 else
281 Signals[i].Handler = SIG_DFL;
286 return sal_True;
289 static sal_Bool DeInitSignal()
291 int i;
292 struct sigaction act;
294 act.sa_flags = 0;
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);
308 return sal_False;
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" );
323 if ( fp )
325 rtlDigest digest = rtl_digest_createMD5();
327 if ( digest )
329 size_t nBytesRead;
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 )
346 nBytesProcessed = 0;
348 rtl_digest_destroyMD5( digest );
351 fclose( fp );
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 )
365 int result = 0;
367 while ( result >= 0 && *string )
369 switch( *string )
371 case '&':
372 result = fputs( "&amp;", stream );
373 break;
374 case '<':
375 result = fputs( "&lt;", stream );
376 break;
377 case '>':
378 result = fputs( "&gt;", stream );
379 break;
380 default:
381 result = fputc( *string, stream );
382 break;
385 string++;
388 return result;
390 #endif
392 /* Create intermediate files and run crash reporter */
394 #define REPORTENV_PARAM "-crashreportenv:"
396 #if defined SAL_ENABLE_CRASH_REPORT && defined INCLUDE_BACKTRACE && \
397 defined LINUX
399 typedef struct
401 const char *name;
402 ElfW(Off) offset;
403 } dynamic_entry;
405 static int
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))
412 int i;
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]);
418 break;
423 if (pDynamic)
425 char buffer[100];
426 int len;
427 char exe[PATH_MAX];
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)
437 exe[len] = '\0';
438 dsoname = exe;
442 if (strcmp(dsoname, entry->name) == 0)
444 entry->offset = pDynamic->p_offset;
445 return 1;
448 return 0;
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
460 * addresses
462 * cmc@openoffice.org
464 static ElfW(Off)
465 dynamic_section_offset(const char *name)
467 dynamic_entry entry;
469 entry.name = name;
470 entry.offset = 0;
472 dl_iterate_phdr(callback, &entry);
474 return entry.offset;
476 #endif
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;
484 sal_uInt32 argi;
485 sal_uInt32 argc;
486 rtl_uString *ustrCommandArg = NULL;
488 if ( !bErrorReportingEnabled )
489 return -1;
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 );
500 return -1;
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 )
518 rtl_uString2String(
519 &strEnv,
520 rtl_uString_getStr( ustrEnvironment ), rtl_uString_getLength( ustrEnvironment ),
521 osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS
524 if ( strEnv )
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 )
543 int i;
544 /* struct sigaction act; */
546 for (i = 0; i < NoSignals; i++)
548 if (Signals[i].Signal == Signal && Signals[i].Action == ACT_ABORT )
550 int ret;
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];
562 int iFrame;
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++ )
598 Dl_info dl_info;
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 "\"",
604 iFrame,
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;
621 if ( dli_fname )
623 ++dli_fname;
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, "/" );
632 else
633 dli_fname = dl_info.dli_fname;
635 /* create checksum of library on stack */
636 if ( dli_fname )
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 )
644 int j;
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",
650 SAL_INT_CAST(
651 unsigned long, nBytesProcessed),
652 dli_fname );
656 if ( dl_info.dli_fbase && dl_info.dli_fname )
658 #ifdef LINUX
659 ElfW(Off) dynamic_offset = dynamic_section_offset(dl_info.dli_fname);
660 fprintf( stackout, " 0x%" SAL_PRI_SIZET "x:", dynamic_offset);
661 #endif
663 fprintf( stackout, " %s + 0x%" SAL_PRI_PTRDIFFT "x",
664 dl_info.dli_fname,
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 );
669 if ( dli_fname )
670 fprintf( xmlout, " name=\"%s\"", dli_fname );
672 if ( dli_fdir )
673 fprintf( xmlout, " path=\"%s\"", dli_fdir );
675 #ifdef LINUX
676 fprintf( xmlout, " dynamicoffset=\"0x%" SAL_PRI_SIZET "x\"", dynamic_offset );
677 #endif
679 else
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" );
709 else
711 pXMLTempName = NULL;
712 pStackTempName = NULL;
713 pChecksumTempName = NULL;
716 if ( stackout )
717 fclose( stackout );
718 if ( xmlout )
719 fclose( xmlout );
720 if ( checksumout )
721 fclose( checksumout );
723 #if defined( LINUX )
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",
727 getpid(),
728 Signal,
729 pXMLTempName,
730 pChecksumTempName,
731 pStackTempName,
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 );
743 rtl_uString2String(
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 ),
756 getpid(),
757 Signal,
758 pXMLTempName,
759 pChecksumTempName,
760 pStackTempName,
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",
771 getpid(),
772 Signal,
773 pXMLTempName,
774 pChecksumTempName,
775 bAutoCrashReport ? " -noui -send" : " -noui" );
776 #endif
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 );
786 if ( pXMLTempName )
787 unlink( pXMLTempName );
789 if ( pStackTempName )
790 unlink( pStackTempName );
792 if ( pChecksumTempName )
793 unlink( pChecksumTempName );
795 if ( -1 != ret )
797 bCrashReporterExecuted = sal_True;
798 return 1;
800 else
801 return -1;
806 return 0;
809 return 1;
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
814 return -1;
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]) );
823 #endif
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" );
829 #else
830 if ( size > 0 )
832 fputs( "Stack:\n", stderr );
833 backtrace_symbols_fd( buffer, size, fileno(stderr) );
835 #endif
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)
847 break;
849 pHandler = pHandler->pNext;
852 return Action;
855 void CallSystemHandler(int Signal)
857 int i;
858 struct sigaction act;
860 for (i = 0; i < NoSignals; i++)
862 if (Signals[i].Signal == Signal)
863 break;
866 if (i < NoSignals)
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() */
877 _exit(255);
878 break;
880 case ACT_ABORT: /* terminate witch core dump */
881 ReportCrash( Signal );
882 act.sa_handler = SIG_DFL;
883 act.sa_flags = 0;
884 sigemptyset(&(act.sa_mask));
885 sigaction(SIGABRT, &act, NULL);
886 PrintStack( Signal );
887 abort();
888 break;
890 case ACT_IGNORE: /* ignore */
891 break;
893 default: /* should never happen */
894 OSL_ASSERT(0);
897 else
898 (*Signals[i].Handler)(Signal);
903 /*****************************************************************************/
904 /* SignalHandlerFunction */
905 /*****************************************************************************/
906 void SignalHandlerFunction(int Signal)
908 oslSignalInfo Info;
909 struct sigaction act;
911 Info.UserSignal = Signal;
912 Info.UserData = NULL;
914 switch (Signal)
916 case SIGBUS:
917 case SIGILL:
918 case SIGSEGV:
919 case SIGIOT:
920 #if ( SIGIOT != SIGABRT )
921 case SIGABRT:
922 #endif
923 Info.Signal = osl_Signal_AccessViolation;
924 break;
926 case -1:
927 Info.Signal = osl_Signal_IntegerDivideByZero;
928 break;
930 case SIGFPE:
931 Info.Signal = osl_Signal_FloatDivideByZero;
932 break;
934 case SIGINT:
935 case SIGTERM:
936 case SIGQUIT:
937 case SIGHUP:
938 Info.Signal = osl_Signal_Terminate;
939 break;
941 default:
942 Info.Signal = osl_Signal_System;
943 break;
946 ReportCrash( Signal );
948 /* Portal Demo HACK !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
949 if (bDoHardKill && (Info.Signal == osl_Signal_AccessViolation))
950 _exit(255);
951 /* Portal Demo HACK !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
954 switch (CallSignalHandler(&Info))
956 case osl_Signal_ActCallNextHdl:
957 CallSystemHandler(Signal);
958 break;
960 case osl_Signal_ActAbortApp:
961 ReportCrash( Signal );
962 act.sa_handler = SIG_DFL;
963 act.sa_flags = 0;
964 sigemptyset(&(act.sa_mask));
965 sigaction(SIGABRT, &act, NULL);
966 PrintStack( Signal );
967 abort();
968 break;
970 case osl_Signal_ActKillApp:
971 /* prevent dumping core on exit() */
972 _exit(255);
973 break;
974 default:
975 break;
979 /*****************************************************************************/
980 /* osl_addSignalHandler */
981 /*****************************************************************************/
982 oslSignalHandler SAL_CALL osl_addSignalHandler(oslSignalHandlerFunction Handler, void* pData)
984 oslSignalHandlerImpl* pHandler;
986 OSL_ASSERT(Handler != NULL);
987 if ( Handler == 0 )
989 return 0;
992 if (! bInitSignal)
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);
1009 return (pHandler);
1012 return (NULL);
1015 /*****************************************************************************/
1016 /* osl_removeSignalHandler */
1017 /*****************************************************************************/
1018 sal_Bool SAL_CALL osl_removeSignalHandler(oslSignalHandler Handler)
1020 oslSignalHandlerImpl *pHandler, *pPrevious = NULL;
1022 OSL_ASSERT(Handler != NULL);
1024 if (! bInitSignal)
1025 bInitSignal = InitSignal();
1027 osl_acquireMutex(SignalListMutex);
1029 pHandler = SignalList;
1031 while (pHandler != NULL)
1033 if (pHandler == Handler)
1035 if (pPrevious)
1036 pPrevious->pNext = pHandler->pNext;
1037 else
1038 SignalList = pHandler->pNext;
1040 osl_releaseMutex(SignalListMutex);
1042 if (SignalList == NULL)
1043 bInitSignal = DeInitSignal();
1045 free(pHandler);
1047 return (sal_True);
1050 pPrevious = pHandler;
1051 pHandler = pHandler->pNext;
1054 osl_releaseMutex(SignalListMutex);
1056 return (sal_False);
1059 /*****************************************************************************/
1060 /* osl_raiseSignal */
1061 /*****************************************************************************/
1062 oslSignalAction SAL_CALL osl_raiseSignal(sal_Int32 UserSignal, void* UserData)
1064 oslSignalInfo Info;
1065 oslSignalAction Action;
1067 if (! bInitSignal)
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);
1080 return (Action);
1083 /*****************************************************************************/
1084 /* osl_setErrorReporting */
1085 /*****************************************************************************/
1086 sal_Bool SAL_CALL osl_setErrorReporting( sal_Bool bEnable )
1088 sal_Bool bOld = bErrorReportingEnabled;
1089 bErrorReportingEnabled = bEnable;
1091 return bOld;