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"
49 #define INCLUDE_BACKTRACE
50 #define STACKTYPE "Linux"
55 #include "backtrace.h"
56 #define INCLUDE_BACKTRACE
59 #define STACKTYPE "Solaris_Sparc"
60 #elif defined( INTEL )
61 #define STACKTYPE "Solaris_X86"
63 #define STACKTYPE "Solaris_Unknown"
66 #endif /* defined SOLARIS */
68 #include <osl/diagnose.h>
69 #include <osl/mutex.h>
70 #include <osl/signal.h>
71 #include <osl/process.h>
72 #include <osl/thread.h>
73 #include <rtl/bootstrap.h>
74 #include <rtl/digest.h>
76 #include "file_path_helper.h"
84 #define MAX_PATH_LEN 2048
86 typedef struct _oslSignalHandlerImpl
88 oslSignalHandlerFunction Handler
;
90 struct _oslSignalHandlerImpl
* pNext
;
91 } oslSignalHandlerImpl
;
93 static struct SignalAction
100 { SIGHUP
, ACT_IGNORE
, NULL
}, /* hangup */
101 { SIGINT
, ACT_EXIT
, NULL
}, /* interrupt (rubout) */
102 { SIGQUIT
, ACT_EXIT
, NULL
}, /* quit (ASCII FS) */
103 { SIGILL
, ACT_SYSTEM
, NULL
}, /* illegal instruction (not reset when caught) */
104 /* changed from ACT_ABOUT to ACT_SYSTEM to try and get collector to run*/
105 { SIGTRAP
, ACT_ABORT
, NULL
}, /* trace trap (not reset when caught) */
106 #if ( SIGIOT != SIGABRT )
107 { SIGIOT
, ACT_ABORT
, NULL
}, /* IOT instruction */
109 { SIGABRT
, ACT_ABORT
, NULL
}, /* used by abort, replace SIGIOT in the future */
111 { SIGEMT
, ACT_SYSTEM
, NULL
}, /* EMT instruction */
112 /* changed from ACT_ABORT to ACT_SYSTEM to remove handler*/
113 /* SIGEMT may also be used by the profiler - so it is probably not a good
114 plan to have the new handler use this signal*/
116 { SIGFPE
, ACT_ABORT
, NULL
}, /* floating point exception */
117 { SIGKILL
, ACT_SYSTEM
, NULL
}, /* kill (cannot be caught or ignored) */
118 { SIGBUS
, ACT_ABORT
, NULL
}, /* bus error */
119 { SIGSEGV
, ACT_ABORT
, NULL
}, /* segmentation violation */
121 { SIGSYS
, ACT_ABORT
, NULL
}, /* bad argument to system call */
123 { SIGPIPE
, ACT_HIDE
, NULL
}, /* write on a pipe with no one to read it */
124 { SIGALRM
, ACT_EXIT
, NULL
}, /* alarm clock */
125 { SIGTERM
, ACT_EXIT
, NULL
}, /* software termination signal from kill */
126 { SIGUSR1
, ACT_SYSTEM
, NULL
}, /* user defined signal 1 */
127 { SIGUSR2
, ACT_SYSTEM
, NULL
}, /* user defined signal 2 */
128 { SIGCHLD
, ACT_SYSTEM
, NULL
}, /* child status change */
130 { SIGPWR
, ACT_IGNORE
, NULL
}, /* power-fail restart */
132 { SIGWINCH
, ACT_IGNORE
, NULL
}, /* window size change */
133 { SIGURG
, ACT_EXIT
, NULL
}, /* urgent socket condition */
135 { SIGPOLL
, ACT_EXIT
, NULL
}, /* pollable event occured */
137 { SIGSTOP
, ACT_SYSTEM
, NULL
}, /* stop (cannot be caught or ignored) */
138 { SIGTSTP
, ACT_SYSTEM
, NULL
}, /* user stop requested from tty */
139 { SIGCONT
, ACT_SYSTEM
, NULL
}, /* stopped process has been continued */
140 { SIGTTIN
, ACT_SYSTEM
, NULL
}, /* background tty read attempted */
141 { SIGTTOU
, ACT_SYSTEM
, NULL
}, /* background tty write attempted */
142 { SIGVTALRM
, ACT_EXIT
, NULL
}, /* virtual timer expired */
143 { SIGPROF
, ACT_SYSTEM
, NULL
}, /* profiling timer expired */
144 /*Change from ACT_EXIT to ACT_SYSTEM for SIGPROF is so that profiling signals do
145 not get taken by the new handler - the new handler does not pass on context
146 information which causes 'collect' to crash. This is a way of avoiding
147 what looks like a bug in the new handler*/
148 { SIGXCPU
, ACT_ABORT
, NULL
}, /* exceeded cpu limit */
149 { SIGXFSZ
, ACT_ABORT
, NULL
} /* exceeded file size limit */
151 const int NoSignals
= sizeof(Signals
) / sizeof(struct SignalAction
);
153 static sal_Bool bErrorReportingEnabled
= sal_True
;
154 static sal_Bool bInitSignal
= sal_False
;
155 static oslMutex SignalListMutex
;
156 static oslSignalHandlerImpl
* SignalList
;
157 static sal_Bool bDoHardKill
= sal_False
;
158 static sal_Bool bSetSEGVHandler
= sal_False
;
159 static sal_Bool bSetWINCHHandler
= sal_False
;
160 static sal_Bool bSetILLHandler
= sal_False
;
162 static void SignalHandlerFunction(int);
164 static void getExecutableName_Impl (rtl_String
** ppstrProgName
)
166 rtl_uString
* ustrProgFile
= 0;
167 osl_getExecutableFile (&ustrProgFile
);
170 rtl_uString
* ustrProgName
= 0;
171 osl_systemPathGetFileNameOrLastDirectoryPart (ustrProgFile
, &ustrProgName
);
172 if (ustrProgName
!= 0)
176 rtl_uString_getStr (ustrProgName
), rtl_uString_getLength (ustrProgName
),
177 osl_getThreadTextEncoding(),
178 OUSTRING_TO_OSTRING_CVTFLAGS
);
179 rtl_uString_release (ustrProgName
);
181 rtl_uString_release (ustrProgFile
);
185 static sal_Bool
is_soffice_Impl (void)
188 rtl_String
* strProgName
= 0;
190 getExecutableName_Impl (&strProgName
);
193 idx
= rtl_str_indexOfStr (rtl_string_getStr (strProgName
), "soffice");
194 rtl_string_release (strProgName
);
199 static sal_Bool
InitSignal()
202 struct sigaction act
;
203 struct sigaction oact
;
205 if (is_soffice_Impl())
209 rtl_uString
*ustrCommandArg
= 0;
211 argc
= osl_getCommandArgCount();
212 for ( argi
= 0; argi
< argc
; argi
++ )
214 if (osl_Process_E_None
== osl_getCommandArg (argi
, &ustrCommandArg
))
216 if (0 == rtl_ustr_ascii_compare (rtl_uString_getStr (ustrCommandArg
), "-bean"))
218 bDoHardKill
= sal_True
;
225 rtl_uString_release (ustrCommandArg
);
229 // WORKAROUND FOR SEGV HANDLER CONFLICT
231 // the java jit needs SIGSEGV for proper work
232 // and we need SIGSEGV for the office crashguard
234 // TEMPORARY SOLUTION:
235 // the office sets the signal handler during startup
236 // java can than overwrite it, if needed
237 bSetSEGVHandler
= sal_True
;
239 // WORKAROUND FOR WINCH HANDLER (SEE ABOVE)
240 bSetWINCHHandler
= sal_True
;
242 // WORKAROUND FOR ILLEGAL INSTRUCTION HANDLER (SEE ABOVE)
243 bSetILLHandler
= sal_True
;
246 SignalListMutex
= osl_createMutex();
248 act
.sa_handler
= SignalHandlerFunction
;
249 act
.sa_flags
= SA_RESTART
;
251 sigfillset(&(act
.sa_mask
));
253 /* Initialize the rest of the signals */
254 for (i
= 0; i
< NoSignals
; i
++)
256 /* hack: stomcatd is attaching JavaVM wich dont work with an sigaction(SEGV) */
257 if ((bSetSEGVHandler
|| Signals
[i
].Signal
!= SIGSEGV
)
258 && (bSetWINCHHandler
|| Signals
[i
].Signal
!= SIGWINCH
)
259 && (bSetILLHandler
|| Signals
[i
].Signal
!= SIGILL
))
261 if (Signals
[i
].Action
!= ACT_SYSTEM
)
263 if (Signals
[i
].Action
== ACT_HIDE
)
265 struct sigaction ign
;
267 ign
.sa_handler
= SIG_IGN
;
269 sigemptyset(&ign
.sa_mask
);
271 if (sigaction(Signals
[i
].Signal
, &ign
, &oact
) == 0)
272 Signals
[i
].Handler
= oact
.sa_handler
;
274 Signals
[i
].Handler
= SIG_DFL
;
277 if (sigaction(Signals
[i
].Signal
, &act
, &oact
) == 0)
278 Signals
[i
].Handler
= oact
.sa_handler
;
280 Signals
[i
].Handler
= SIG_DFL
;
288 static sal_Bool
DeInitSignal()
291 struct sigaction act
;
294 sigemptyset(&(act
.sa_mask
));
296 /* Initialize the rest of the signals */
297 for (i
= NoSignals
- 1; i
>= 0; i
--)
298 if (Signals
[i
].Action
!= ACT_SYSTEM
)
300 act
.sa_handler
= Signals
[i
].Handler
;
302 sigaction(Signals
[i
].Signal
, &act
, NULL
);
305 osl_destroyMutex(SignalListMutex
);
310 #if defined (SAL_ENABLE_CRASH_REPORT) && defined(INCLUDE_BACKTRACE)
312 /*****************************************************************************/
313 /* Generate MD5 checksum */
314 /*****************************************************************************/
316 static sal_uInt32
calc_md5_checksum( const char *filename
, sal_uInt8
*pChecksum
, sal_uInt32 nChecksumLen
)
318 sal_uInt32 nBytesProcessed
= 0;
320 FILE *fp
= fopen( filename
, "r" );
324 rtlDigest digest
= rtl_digest_createMD5();
329 sal_uInt8 buffer
[4096];
330 rtlDigestError error
= rtl_Digest_E_None
;
332 while ( rtl_Digest_E_None
== error
&&
333 0 != (nBytesRead
= fread( buffer
, 1, sizeof(buffer
), fp
)) )
335 error
= rtl_digest_updateMD5( digest
, buffer
, nBytesRead
);
336 nBytesProcessed
+= nBytesRead
;
339 if ( rtl_Digest_E_None
== error
)
341 error
= rtl_digest_getMD5( digest
, pChecksum
, nChecksumLen
);
344 if ( rtl_Digest_E_None
!= error
)
347 rtl_digest_destroyMD5( digest
);
353 return nBytesProcessed
;
356 /*****************************************************************************/
357 /* Call crash reporter */
358 /*****************************************************************************/
360 /* Helper function to encode and write a string to a stream */
362 static int fputs_xml( const char *string
, FILE *stream
)
366 while ( result
>= 0 && *string
)
371 result
= fputs( "&", stream
);
374 result
= fputs( "<", stream
);
377 result
= fputs( ">", stream
);
380 result
= fputc( *string
, stream
);
391 /* Create intermediate files and run crash reporter */
393 #define REPORTENV_PARAM "-crashreportenv:"
395 static int ReportCrash( int Signal
)
397 #ifdef SAL_ENABLE_CRASH_REPORT
398 static sal_Bool bCrashReporterExecuted
= sal_False
;
399 sal_Bool bAutoCrashReport
= sal_False
;
403 rtl_uString
*ustrCommandArg
= NULL
;
405 if ( !bErrorReportingEnabled
)
408 argc
= osl_getCommandArgCount();
410 for ( argi
= 0; argi
< argc
; argi
++ )
412 if ( osl_Process_E_None
== osl_getCommandArg( argi
, &ustrCommandArg
) )
414 if ( 0 == rtl_ustr_ascii_compare( rtl_uString_getStr( ustrCommandArg
), "-nocrashreport" ) )
416 rtl_uString_release( ustrCommandArg
);
419 else if ( 0 == rtl_ustr_ascii_compare( rtl_uString_getStr( ustrCommandArg
), "-autocrashreport" ) )
421 bAutoCrashReport
= sal_True
;
423 else if ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength(
424 rtl_uString_getStr( ustrCommandArg
), rtl_uString_getLength( ustrCommandArg
),
425 REPORTENV_PARAM
, strlen(REPORTENV_PARAM
) )
428 rtl_uString
*ustrEnvironment
= NULL
;
429 rtl_String
*strEnv
= NULL
;
431 rtl_uString_newFromStr( &ustrEnvironment
, rtl_uString_getStr( ustrCommandArg
) + strlen(REPORTENV_PARAM
) );
433 if ( ustrEnvironment
)
437 rtl_uString_getStr( ustrEnvironment
), rtl_uString_getLength( ustrEnvironment
),
438 osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS
443 putenv( rtl_string_getStr( strEnv
) );
444 rtl_string_release( strEnv
);
447 rtl_uString_release( ustrEnvironment
);
455 if ( ustrCommandArg
)
456 rtl_uString_release( ustrCommandArg
);
458 if ( !bCrashReporterExecuted
)
461 /* struct sigaction act; */
463 for (i
= 0; i
< NoSignals
; i
++)
465 if (Signals
[i
].Signal
== Signal
&& Signals
[i
].Action
== ACT_ABORT
)
468 char szShellCmd
[512];
469 char *pXMLTempName
= NULL
;
470 char *pStackTempName
= NULL
;
471 char *pChecksumTempName
= NULL
;
473 #ifdef INCLUDE_BACKTRACE
474 char szXMLTempNameBuffer
[L_tmpnam
];
475 char szChecksumTempNameBuffer
[L_tmpnam
];
476 char szStackTempNameBuffer
[L_tmpnam
];
478 void *stackframes
[MAX_STACK_FRAMES
];
480 int nFrames
= backtrace( stackframes
, sizeof(stackframes
)/sizeof(stackframes
[0]));
482 FILE *xmlout
= NULL
, *stackout
= NULL
, *checksumout
= NULL
;
483 int fdxml
, fdstk
, fdchksum
;
485 strncpy( szXMLTempNameBuffer
, P_tmpdir
, sizeof(szXMLTempNameBuffer
) );
486 strncat( szXMLTempNameBuffer
, "/crxmlXXXXXX", sizeof(szXMLTempNameBuffer
) );
488 strncpy( szStackTempNameBuffer
, P_tmpdir
, sizeof(szStackTempNameBuffer
) );
489 strncat( szStackTempNameBuffer
, "/crstkXXXXXX", sizeof(szStackTempNameBuffer
) );
491 strncpy( szChecksumTempNameBuffer
, P_tmpdir
, sizeof(szChecksumTempNameBuffer
) );
492 strncat( szChecksumTempNameBuffer
, "/crchkXXXXXX", sizeof(szChecksumTempNameBuffer
) );
494 fdxml
= mkstemp(szXMLTempNameBuffer
);
495 fdstk
= mkstemp(szStackTempNameBuffer
);
496 fdchksum
= mkstemp(szChecksumTempNameBuffer
);
498 xmlout
= fdopen( fdxml
, "w" );
499 stackout
= fdopen( fdstk
, "w" );
500 checksumout
= fdopen( fdchksum
, "w" );
502 pXMLTempName
= szXMLTempNameBuffer
;
503 pStackTempName
= szStackTempNameBuffer
;
504 pChecksumTempName
= szChecksumTempNameBuffer
;
507 if ( xmlout
&& stackout
&& checksumout
)
509 fprintf( xmlout
, "<errormail:Stack type=\"%s\">\n", STACKTYPE
);
511 fprintf( checksumout
, "<errormail:Checksums type=\"MD5\">\n" );
513 for ( iFrame
= 0; iFrame
< nFrames
; iFrame
++ )
517 fprintf( stackout
, "0x%" SAL_PRIxUINTPTR
":",
518 SAL_INT_CAST(sal_uIntPtr
, stackframes
[iFrame
]) );
520 fprintf( xmlout
, "<errormail:StackInfo pos=\"%d\" ip=\"0x%" SAL_PRIxUINTPTR
"\"",
522 SAL_INT_CAST(sal_uIntPtr
, stackframes
[iFrame
])
525 memset( &dl_info
, 0, sizeof(dl_info
) );
527 /* dladdr may fail */
528 if ( dladdr( stackframes
[iFrame
], &dl_info
) )
530 const char *dli_fname
= NULL
;
531 char *dli_fdir
= NULL
;
532 char szDirectory
[PATH_MAX
];
533 char szCanonicDirectory
[PATH_MAX
];
535 /* Don't expect that dladdr filled all members of dl_info */
537 dli_fname
= dl_info
.dli_fname
? strrchr( dl_info
.dli_fname
, '/' ) : NULL
;
541 memcpy( szDirectory
, dl_info
.dli_fname
, dli_fname
- dl_info
.dli_fname
);
542 szDirectory
[dli_fname
- dl_info
.dli_fname
] = 0;
544 dli_fdir
= realpath( szDirectory
, szCanonicDirectory
) ? szCanonicDirectory
: szDirectory
;
546 if ( *dli_fdir
&& dli_fdir
[ strlen(dli_fdir
) - 1 ] != '/' )
547 strcat( dli_fdir
, "/" );
550 dli_fname
= dl_info
.dli_fname
;
552 /* create checksum of library on stack */
555 sal_uInt8 checksum
[RTL_DIGEST_LENGTH_MD5
];
557 sal_uInt32 nBytesProcessed
= calc_md5_checksum(
558 dl_info
.dli_fname
, checksum
, sizeof(checksum
) );
559 if ( nBytesProcessed
)
563 fprintf( checksumout
, "<errormail:Checksum sum=\"0x" );
564 for ( j
= 0; j
< 16; fprintf( checksumout
, "%02X", checksum
[j
++] ) );
565 fprintf( checksumout
,
566 "\" bytes=\"%lu\" file=\"%s\"/>\n",
568 unsigned long, nBytesProcessed
),
573 if ( dl_info
.dli_fbase
&& dl_info
.dli_fname
)
575 fprintf( stackout
, " %s + 0x%" SAL_PRI_PTRDIFFT
"x",
577 (char*)stackframes
[iFrame
] - (char*)dl_info
.dli_fbase
580 fprintf( xmlout
, " rel=\"0x%" SAL_PRI_PTRDIFFT
"x\"", (char *)stackframes
[iFrame
] - (char *)dl_info
.dli_fbase
);
582 fprintf( xmlout
, " name=\"%s\"", dli_fname
);
585 fprintf( xmlout
, " path=\"%s\"", dli_fdir
);
588 fprintf( stackout
, " ????????" );
590 if ( dl_info
.dli_sname
&& dl_info
.dli_saddr
)
592 fputs( " (", stackout
);
593 fputs_xml( dl_info
.dli_sname
, stackout
);
594 fprintf( stackout
, " + 0x%" SAL_PRI_PTRDIFFT
"x)",
595 (char*)stackframes
[iFrame
] - (char*)dl_info
.dli_saddr
);
597 fputs( " ordinal=\"", xmlout
);
598 fputs_xml( dl_info
.dli_sname
, xmlout
);
599 fprintf( xmlout
, "+0x%" SAL_PRI_PTRDIFFT
"x\"",
600 (char *)stackframes
[iFrame
] - (char *)dl_info
.dli_saddr
);
604 else /* dladdr failed */
606 fprintf( stackout
, " ????????" );
609 fprintf( stackout
, "\n" );
610 fprintf( xmlout
, "/>\n" );
614 fprintf( xmlout
, "</errormail:Stack>\n" );
615 fprintf( checksumout
, "</errormail:Checksums>\n" );
620 pStackTempName
= NULL
;
621 pChecksumTempName
= NULL
;
629 fclose( checksumout
);
632 if ( pXMLTempName
&& pChecksumTempName
&& pStackTempName
)
633 snprintf( szShellCmd
, sizeof(szShellCmd
)/sizeof(szShellCmd
[0]),
634 "crash_report -p %d -s %d -xml %s -chksum %s -stack %s%s",
640 bAutoCrashReport
? " -noui -send" : " -noui" );
641 #elif defined( MACOSX )
642 if ( pXMLTempName
&& pChecksumTempName
&& pStackTempName
)
644 rtl_uString
*crashrep_url
= NULL
;
645 rtl_uString
*crashrep_path
= NULL
;
646 rtl_String
*crashrep_path_system
= NULL
;
648 rtl_string2UString( &crashrep_url
, RTL_CONSTASCII_USTRINGPARAM("$BRAND_BASE_DIR/program/crash_report.bin"), OSTRING_TO_OUSTRING_CVTFLAGS
);
649 rtl_bootstrap_expandMacros( &crashrep_url
);
650 osl_getSystemPathFromFileURL( crashrep_url
, &crashrep_path
);
652 &crashrep_path_system
,
653 rtl_uString_getStr( crashrep_path
),
654 rtl_uString_getLength( crashrep_path
),
655 osl_getThreadTextEncoding(),
656 RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
| RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR
);
658 rtl_uString_release( crashrep_url
);
659 rtl_uString_release( crashrep_path
);
661 snprintf( szShellCmd
, sizeof(szShellCmd
)/sizeof(szShellCmd
[0]),
662 "%s -p %d -s %d -xml %s -chksum %s -stack %s%s",
663 rtl_string_getStr( crashrep_path_system
),
669 bAutoCrashReport
? " -noui -send" : " -noui" );
671 rtl_string_release( crashrep_path_system
);
673 printf( "%s\n", szShellCmd
);
675 #elif defined ( SOLARIS )
676 if ( pXMLTempName
&& pChecksumTempName
)
677 snprintf( szShellCmd
, sizeof(szShellCmd
)/sizeof(szShellCmd
[0]),
678 "crash_report -p %d -s %d -xml %s -chksum %s%s",
683 bAutoCrashReport
? " -noui -send" : " -noui" );
686 #else /* defined INCLUDE BACKTRACE */
687 snprintf( szShellCmd
, sizeof(szShellCmd
)/sizeof(szShellCmd
[0]),
688 "crash_report -p %d -s %d%s", getpid(), Signal
, bAutoCrashReport
? " -noui -send" : " -noui" );
689 #endif /* defined INCLUDE BACKTRACE */
692 ret
= system( szShellCmd
);
695 unlink( pXMLTempName
);
697 if ( pStackTempName
)
698 unlink( pStackTempName
);
700 if ( pChecksumTempName
)
701 unlink( pChecksumTempName
);
705 bCrashReporterExecuted
= sal_True
;
718 #else /* defined SAL_ENABLE_CRASH_REPORT */
719 /* the utility crash_report is not build, so do the same as when
720 the option -nocrashreport is used */
721 (void) Signal
; // avoid warnings
723 #endif /* defined SAL_ENABLE_CRASH_REPORT */
726 static void PrintStack( int sig
)
728 #if ! defined(MACOSX) || defined(INCLUDE_BACKTRACE)
729 void *buffer
[MAX_STACK_FRAMES
];
730 int size
= backtrace( buffer
, sizeof(buffer
) / sizeof(buffer
[0]) );
733 fprintf( stderr
, "\n\nFatal exception: Signal %d\n", sig
);
735 #if defined(MACOSX) && ! defined(INCLUDE_BACKTRACE)
736 fprintf( stderr
, "Please turn on Enable Crash Reporting and\nAutomatic Display of Crashlogs in the Console application\n" );
740 fputs( "Stack:\n", stderr
);
741 backtrace_symbols_fd( buffer
, size
, fileno(stderr
) );
746 static oslSignalAction
CallSignalHandler(oslSignalInfo
*pInfo
)
748 oslSignalHandlerImpl
* pHandler
= SignalList
;
749 oslSignalAction Action
= osl_Signal_ActCallNextHdl
;
751 while (pHandler
!= NULL
)
753 if ((Action
= pHandler
->Handler(pHandler
->pData
, pInfo
))
754 != osl_Signal_ActCallNextHdl
)
757 pHandler
= pHandler
->pNext
;
763 void CallSystemHandler(int Signal
)
766 struct sigaction act
;
768 for (i
= 0; i
< NoSignals
; i
++)
770 if (Signals
[i
].Signal
== Signal
)
776 if ((Signals
[i
].Handler
== NULL
) ||
777 (Signals
[i
].Handler
== SIG_DFL
) ||
778 (Signals
[i
].Handler
== SIG_IGN
) ||
779 (Signals
[i
].Handler
== SIG_ERR
))
781 switch (Signals
[i
].Action
)
783 case ACT_EXIT
: /* terminate */
784 /* prevent dumping core on exit() */
788 case ACT_ABORT
: /* terminate witch core dump */
789 ReportCrash( Signal
);
790 act
.sa_handler
= SIG_DFL
;
792 sigemptyset(&(act
.sa_mask
));
793 sigaction(SIGABRT
, &act
, NULL
);
794 PrintStack( Signal
);
798 case ACT_IGNORE
: /* ignore */
801 default: /* should never happen */
806 (*Signals
[i
].Handler
)(Signal
);
811 /*****************************************************************************/
812 /* SignalHandlerFunction */
813 /*****************************************************************************/
814 void SignalHandlerFunction(int Signal
)
817 struct sigaction act
;
819 Info
.UserSignal
= Signal
;
820 Info
.UserData
= NULL
;
828 #if ( SIGIOT != SIGABRT )
831 Info
.Signal
= osl_Signal_AccessViolation
;
835 Info
.Signal
= osl_Signal_IntegerDivideByZero
;
839 Info
.Signal
= osl_Signal_FloatDivideByZero
;
846 Info
.Signal
= osl_Signal_Terminate
;
850 Info
.Signal
= osl_Signal_System
;
854 ReportCrash( Signal
);
856 /* Portal Demo HACK !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
857 if (bDoHardKill
&& (Info
.Signal
== osl_Signal_AccessViolation
))
859 /* Portal Demo HACK !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
862 switch (CallSignalHandler(&Info
))
864 case osl_Signal_ActCallNextHdl
:
865 CallSystemHandler(Signal
);
868 case osl_Signal_ActAbortApp
:
869 ReportCrash( Signal
);
870 act
.sa_handler
= SIG_DFL
;
872 sigemptyset(&(act
.sa_mask
));
873 sigaction(SIGABRT
, &act
, NULL
);
874 PrintStack( Signal
);
878 case osl_Signal_ActKillApp
:
879 /* prevent dumping core on exit() */
887 /*****************************************************************************/
888 /* osl_addSignalHandler */
889 /*****************************************************************************/
890 oslSignalHandler SAL_CALL
osl_addSignalHandler(oslSignalHandlerFunction Handler
, void* pData
)
892 oslSignalHandlerImpl
* pHandler
;
894 OSL_ASSERT(Handler
!= NULL
);
901 bInitSignal
= InitSignal();
903 pHandler
= (oslSignalHandlerImpl
*) calloc(1, sizeof(oslSignalHandlerImpl
));
905 if (pHandler
!= NULL
)
907 pHandler
->Handler
= Handler
;
908 pHandler
->pData
= pData
;
910 osl_acquireMutex(SignalListMutex
);
912 pHandler
->pNext
= SignalList
;
913 SignalList
= pHandler
;
915 osl_releaseMutex(SignalListMutex
);
923 /*****************************************************************************/
924 /* osl_removeSignalHandler */
925 /*****************************************************************************/
926 sal_Bool SAL_CALL
osl_removeSignalHandler(oslSignalHandler Handler
)
928 oslSignalHandlerImpl
*pHandler
, *pPrevious
= NULL
;
930 OSL_ASSERT(Handler
!= NULL
);
933 bInitSignal
= InitSignal();
935 osl_acquireMutex(SignalListMutex
);
937 pHandler
= SignalList
;
939 while (pHandler
!= NULL
)
941 if (pHandler
== Handler
)
944 pPrevious
->pNext
= pHandler
->pNext
;
946 SignalList
= pHandler
->pNext
;
948 osl_releaseMutex(SignalListMutex
);
950 if (SignalList
== NULL
)
951 bInitSignal
= DeInitSignal();
958 pPrevious
= pHandler
;
959 pHandler
= pHandler
->pNext
;
962 osl_releaseMutex(SignalListMutex
);
967 /*****************************************************************************/
968 /* osl_raiseSignal */
969 /*****************************************************************************/
970 oslSignalAction SAL_CALL
osl_raiseSignal(sal_Int32 UserSignal
, void* UserData
)
973 oslSignalAction Action
;
976 bInitSignal
= InitSignal();
978 osl_acquireMutex(SignalListMutex
);
980 Info
.Signal
= osl_Signal_User
;
981 Info
.UserSignal
= UserSignal
;
982 Info
.UserData
= UserData
;
984 Action
= CallSignalHandler(&Info
);
986 osl_releaseMutex(SignalListMutex
);
991 /*****************************************************************************/
992 /* osl_setErrorReporting */
993 /*****************************************************************************/
994 sal_Bool SAL_CALL
osl_setErrorReporting( sal_Bool bEnable
)
996 sal_Bool bOld
= bErrorReportingEnabled
;
997 bErrorReportingEnabled
= bEnable
;