1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir 29*cdf0e10cSrcweir /* system headers */ 30*cdf0e10cSrcweir #include "system.h" 31*cdf0e10cSrcweir 32*cdf0e10cSrcweir #define MAX_STACK_FRAMES 256 33*cdf0e10cSrcweir 34*cdf0e10cSrcweir #if defined( MACOSX ) 35*cdf0e10cSrcweir 36*cdf0e10cSrcweir #if defined( INTEL ) 37*cdf0e10cSrcweir #include "backtrace.h" 38*cdf0e10cSrcweir #define INCLUDE_BACKTRACE 39*cdf0e10cSrcweir #define STACKTYPE "MacOsX_X86" 40*cdf0e10cSrcweir #endif /* INTEL */ 41*cdf0e10cSrcweir 42*cdf0e10cSrcweir #endif /* MACOSX */ 43*cdf0e10cSrcweir 44*cdf0e10cSrcweir #ifdef LINUX 45*cdf0e10cSrcweir #include <execinfo.h> 46*cdf0e10cSrcweir #include <link.h> 47*cdf0e10cSrcweir #define INCLUDE_BACKTRACE 48*cdf0e10cSrcweir #define STACKTYPE "Linux" 49*cdf0e10cSrcweir #endif 50*cdf0e10cSrcweir 51*cdf0e10cSrcweir #ifdef SOLARIS 52*cdf0e10cSrcweir 53*cdf0e10cSrcweir #include "backtrace.h" 54*cdf0e10cSrcweir #define INCLUDE_BACKTRACE 55*cdf0e10cSrcweir 56*cdf0e10cSrcweir #if defined( SPARC ) 57*cdf0e10cSrcweir #define STACKTYPE "Solaris_Sparc" 58*cdf0e10cSrcweir #elif defined( INTEL ) 59*cdf0e10cSrcweir #define STACKTYPE "Solaris_X86" 60*cdf0e10cSrcweir #else 61*cdf0e10cSrcweir #define STACKTYPE "Solaris_Unknown" 62*cdf0e10cSrcweir #endif 63*cdf0e10cSrcweir 64*cdf0e10cSrcweir #endif /* defined SOLARIS */ 65*cdf0e10cSrcweir 66*cdf0e10cSrcweir #include <osl/diagnose.h> 67*cdf0e10cSrcweir #include <osl/mutex.h> 68*cdf0e10cSrcweir #include <osl/signal.h> 69*cdf0e10cSrcweir #include <osl/process.h> 70*cdf0e10cSrcweir #include <osl/thread.h> 71*cdf0e10cSrcweir #include <rtl/bootstrap.h> 72*cdf0e10cSrcweir #include <rtl/digest.h> 73*cdf0e10cSrcweir 74*cdf0e10cSrcweir #include "file_path_helper.h" 75*cdf0e10cSrcweir 76*cdf0e10cSrcweir #define ACT_IGNORE 1 77*cdf0e10cSrcweir #define ACT_EXIT 2 78*cdf0e10cSrcweir #define ACT_SYSTEM 3 79*cdf0e10cSrcweir #define ACT_HIDE 4 80*cdf0e10cSrcweir #ifdef SAL_ENABLE_CRASH_REPORT 81*cdf0e10cSrcweir # define ACT_ABORT 5 82*cdf0e10cSrcweir #else 83*cdf0e10cSrcweir # define ACT_ABORT ACT_SYSTEM 84*cdf0e10cSrcweir #endif 85*cdf0e10cSrcweir 86*cdf0e10cSrcweir #define MAX_PATH_LEN 2048 87*cdf0e10cSrcweir 88*cdf0e10cSrcweir typedef struct _oslSignalHandlerImpl 89*cdf0e10cSrcweir { 90*cdf0e10cSrcweir oslSignalHandlerFunction Handler; 91*cdf0e10cSrcweir void* pData; 92*cdf0e10cSrcweir struct _oslSignalHandlerImpl* pNext; 93*cdf0e10cSrcweir } oslSignalHandlerImpl; 94*cdf0e10cSrcweir 95*cdf0e10cSrcweir static struct SignalAction 96*cdf0e10cSrcweir { 97*cdf0e10cSrcweir int Signal; 98*cdf0e10cSrcweir int Action; 99*cdf0e10cSrcweir void (*Handler)(int); 100*cdf0e10cSrcweir } Signals[] = 101*cdf0e10cSrcweir { 102*cdf0e10cSrcweir { SIGHUP, ACT_IGNORE, NULL }, /* hangup */ 103*cdf0e10cSrcweir { SIGINT, ACT_EXIT, NULL }, /* interrupt (rubout) */ 104*cdf0e10cSrcweir { SIGQUIT, ACT_EXIT, NULL }, /* quit (ASCII FS) */ 105*cdf0e10cSrcweir { SIGILL, ACT_SYSTEM, NULL }, /* illegal instruction (not reset when caught) */ 106*cdf0e10cSrcweir /* changed from ACT_ABOUT to ACT_SYSTEM to try and get collector to run*/ 107*cdf0e10cSrcweir { SIGTRAP, ACT_ABORT, NULL }, /* trace trap (not reset when caught) */ 108*cdf0e10cSrcweir #if ( SIGIOT != SIGABRT ) 109*cdf0e10cSrcweir { SIGIOT, ACT_ABORT, NULL }, /* IOT instruction */ 110*cdf0e10cSrcweir #endif 111*cdf0e10cSrcweir { SIGABRT, ACT_ABORT, NULL }, /* used by abort, replace SIGIOT in the future */ 112*cdf0e10cSrcweir #ifdef SIGEMT 113*cdf0e10cSrcweir { SIGEMT, ACT_SYSTEM, NULL }, /* EMT instruction */ 114*cdf0e10cSrcweir /* changed from ACT_ABORT to ACT_SYSTEM to remove handler*/ 115*cdf0e10cSrcweir /* SIGEMT may also be used by the profiler - so it is probably not a good 116*cdf0e10cSrcweir plan to have the new handler use this signal*/ 117*cdf0e10cSrcweir #endif 118*cdf0e10cSrcweir { SIGFPE, ACT_ABORT, NULL }, /* floating point exception */ 119*cdf0e10cSrcweir { SIGKILL, ACT_SYSTEM, NULL }, /* kill (cannot be caught or ignored) */ 120*cdf0e10cSrcweir { SIGBUS, ACT_ABORT, NULL }, /* bus error */ 121*cdf0e10cSrcweir { SIGSEGV, ACT_ABORT, NULL }, /* segmentation violation */ 122*cdf0e10cSrcweir #ifdef SIGSYS 123*cdf0e10cSrcweir { SIGSYS, ACT_ABORT, NULL }, /* bad argument to system call */ 124*cdf0e10cSrcweir #endif 125*cdf0e10cSrcweir { SIGPIPE, ACT_HIDE, NULL }, /* write on a pipe with no one to read it */ 126*cdf0e10cSrcweir { SIGALRM, ACT_EXIT, NULL }, /* alarm clock */ 127*cdf0e10cSrcweir { SIGTERM, ACT_EXIT, NULL }, /* software termination signal from kill */ 128*cdf0e10cSrcweir { SIGUSR1, ACT_SYSTEM, NULL }, /* user defined signal 1 */ 129*cdf0e10cSrcweir { SIGUSR2, ACT_SYSTEM, NULL }, /* user defined signal 2 */ 130*cdf0e10cSrcweir { SIGCHLD, ACT_SYSTEM, NULL }, /* child status change */ 131*cdf0e10cSrcweir #ifdef SIGPWR 132*cdf0e10cSrcweir { SIGPWR, ACT_IGNORE, NULL }, /* power-fail restart */ 133*cdf0e10cSrcweir #endif 134*cdf0e10cSrcweir { SIGWINCH, ACT_IGNORE, NULL }, /* window size change */ 135*cdf0e10cSrcweir { SIGURG, ACT_EXIT, NULL }, /* urgent socket condition */ 136*cdf0e10cSrcweir #ifdef SIGPOLL 137*cdf0e10cSrcweir { SIGPOLL, ACT_EXIT, NULL }, /* pollable event occured */ 138*cdf0e10cSrcweir #endif 139*cdf0e10cSrcweir { SIGSTOP, ACT_SYSTEM, NULL }, /* stop (cannot be caught or ignored) */ 140*cdf0e10cSrcweir { SIGTSTP, ACT_SYSTEM, NULL }, /* user stop requested from tty */ 141*cdf0e10cSrcweir { SIGCONT, ACT_SYSTEM, NULL }, /* stopped process has been continued */ 142*cdf0e10cSrcweir { SIGTTIN, ACT_SYSTEM, NULL }, /* background tty read attempted */ 143*cdf0e10cSrcweir { SIGTTOU, ACT_SYSTEM, NULL }, /* background tty write attempted */ 144*cdf0e10cSrcweir { SIGVTALRM, ACT_EXIT, NULL }, /* virtual timer expired */ 145*cdf0e10cSrcweir { SIGPROF, ACT_SYSTEM, NULL }, /* profiling timer expired */ 146*cdf0e10cSrcweir /*Change from ACT_EXIT to ACT_SYSTEM for SIGPROF is so that profiling signals do 147*cdf0e10cSrcweir not get taken by the new handler - the new handler does not pass on context 148*cdf0e10cSrcweir information which causes 'collect' to crash. This is a way of avoiding 149*cdf0e10cSrcweir what looks like a bug in the new handler*/ 150*cdf0e10cSrcweir { SIGXCPU, ACT_ABORT, NULL }, /* exceeded cpu limit */ 151*cdf0e10cSrcweir { SIGXFSZ, ACT_ABORT, NULL } /* exceeded file size limit */ 152*cdf0e10cSrcweir }; 153*cdf0e10cSrcweir const int NoSignals = sizeof(Signals) / sizeof(struct SignalAction); 154*cdf0e10cSrcweir 155*cdf0e10cSrcweir static sal_Bool bErrorReportingEnabled = sal_True; 156*cdf0e10cSrcweir static sal_Bool bInitSignal = sal_False; 157*cdf0e10cSrcweir static oslMutex SignalListMutex; 158*cdf0e10cSrcweir static oslSignalHandlerImpl* SignalList; 159*cdf0e10cSrcweir static sal_Bool bDoHardKill = sal_False; 160*cdf0e10cSrcweir static sal_Bool bSetSEGVHandler = sal_False; 161*cdf0e10cSrcweir static sal_Bool bSetWINCHHandler = sal_False; 162*cdf0e10cSrcweir static sal_Bool bSetILLHandler = sal_False; 163*cdf0e10cSrcweir 164*cdf0e10cSrcweir static void SignalHandlerFunction(int); 165*cdf0e10cSrcweir 166*cdf0e10cSrcweir static void getExecutableName_Impl (rtl_String ** ppstrProgName) 167*cdf0e10cSrcweir { 168*cdf0e10cSrcweir rtl_uString * ustrProgFile = 0; 169*cdf0e10cSrcweir osl_getExecutableFile (&ustrProgFile); 170*cdf0e10cSrcweir if (ustrProgFile) 171*cdf0e10cSrcweir { 172*cdf0e10cSrcweir rtl_uString * ustrProgName = 0; 173*cdf0e10cSrcweir osl_systemPathGetFileNameOrLastDirectoryPart (ustrProgFile, &ustrProgName); 174*cdf0e10cSrcweir if (ustrProgName != 0) 175*cdf0e10cSrcweir { 176*cdf0e10cSrcweir rtl_uString2String ( 177*cdf0e10cSrcweir ppstrProgName, 178*cdf0e10cSrcweir rtl_uString_getStr (ustrProgName), rtl_uString_getLength (ustrProgName), 179*cdf0e10cSrcweir osl_getThreadTextEncoding(), 180*cdf0e10cSrcweir OUSTRING_TO_OSTRING_CVTFLAGS); 181*cdf0e10cSrcweir rtl_uString_release (ustrProgName); 182*cdf0e10cSrcweir } 183*cdf0e10cSrcweir rtl_uString_release (ustrProgFile); 184*cdf0e10cSrcweir } 185*cdf0e10cSrcweir } 186*cdf0e10cSrcweir 187*cdf0e10cSrcweir static sal_Bool is_soffice_Impl (void) 188*cdf0e10cSrcweir { 189*cdf0e10cSrcweir sal_Int32 idx = -1; 190*cdf0e10cSrcweir rtl_String * strProgName = 0; 191*cdf0e10cSrcweir 192*cdf0e10cSrcweir getExecutableName_Impl (&strProgName); 193*cdf0e10cSrcweir if (strProgName) 194*cdf0e10cSrcweir { 195*cdf0e10cSrcweir idx = rtl_str_indexOfStr (rtl_string_getStr (strProgName), "soffice"); 196*cdf0e10cSrcweir rtl_string_release (strProgName); 197*cdf0e10cSrcweir } 198*cdf0e10cSrcweir return (idx != -1); 199*cdf0e10cSrcweir } 200*cdf0e10cSrcweir 201*cdf0e10cSrcweir static sal_Bool InitSignal() 202*cdf0e10cSrcweir { 203*cdf0e10cSrcweir int i; 204*cdf0e10cSrcweir struct sigaction act; 205*cdf0e10cSrcweir struct sigaction oact; 206*cdf0e10cSrcweir sigset_t unset; 207*cdf0e10cSrcweir 208*cdf0e10cSrcweir if (is_soffice_Impl()) 209*cdf0e10cSrcweir { 210*cdf0e10cSrcweir sal_uInt32 argi; 211*cdf0e10cSrcweir sal_uInt32 argc; 212*cdf0e10cSrcweir rtl_uString *ustrCommandArg = 0; 213*cdf0e10cSrcweir 214*cdf0e10cSrcweir argc = osl_getCommandArgCount(); 215*cdf0e10cSrcweir for ( argi = 0; argi < argc; argi++ ) 216*cdf0e10cSrcweir { 217*cdf0e10cSrcweir if (osl_Process_E_None == osl_getCommandArg (argi, &ustrCommandArg)) 218*cdf0e10cSrcweir { 219*cdf0e10cSrcweir if (0 == rtl_ustr_ascii_compare (rtl_uString_getStr (ustrCommandArg), "-bean")) 220*cdf0e10cSrcweir { 221*cdf0e10cSrcweir bDoHardKill = sal_True; 222*cdf0e10cSrcweir break; 223*cdf0e10cSrcweir } 224*cdf0e10cSrcweir } 225*cdf0e10cSrcweir } 226*cdf0e10cSrcweir if (ustrCommandArg) 227*cdf0e10cSrcweir { 228*cdf0e10cSrcweir rtl_uString_release (ustrCommandArg); 229*cdf0e10cSrcweir ustrCommandArg = 0; 230*cdf0e10cSrcweir } 231*cdf0e10cSrcweir 232*cdf0e10cSrcweir // WORKAROUND FOR SEGV HANDLER CONFLICT 233*cdf0e10cSrcweir // 234*cdf0e10cSrcweir // the java jit needs SIGSEGV for proper work 235*cdf0e10cSrcweir // and we need SIGSEGV for the office crashguard 236*cdf0e10cSrcweir // 237*cdf0e10cSrcweir // TEMPORARY SOLUTION: 238*cdf0e10cSrcweir // the office sets the signal handler during startup 239*cdf0e10cSrcweir // java can than overwrite it, if needed 240*cdf0e10cSrcweir bSetSEGVHandler = sal_True; 241*cdf0e10cSrcweir 242*cdf0e10cSrcweir // WORKAROUND FOR WINCH HANDLER (SEE ABOVE) 243*cdf0e10cSrcweir bSetWINCHHandler = sal_True; 244*cdf0e10cSrcweir 245*cdf0e10cSrcweir // WORKAROUND FOR ILLEGAL INSTRUCTION HANDLER (SEE ABOVE) 246*cdf0e10cSrcweir bSetILLHandler = sal_True; 247*cdf0e10cSrcweir } 248*cdf0e10cSrcweir 249*cdf0e10cSrcweir SignalListMutex = osl_createMutex(); 250*cdf0e10cSrcweir 251*cdf0e10cSrcweir act.sa_handler = SignalHandlerFunction; 252*cdf0e10cSrcweir act.sa_flags = SA_RESTART; 253*cdf0e10cSrcweir 254*cdf0e10cSrcweir sigfillset(&(act.sa_mask)); 255*cdf0e10cSrcweir 256*cdf0e10cSrcweir /* Initialize the rest of the signals */ 257*cdf0e10cSrcweir for (i = 0; i < NoSignals; i++) 258*cdf0e10cSrcweir { 259*cdf0e10cSrcweir /* hack: stomcatd is attaching JavaVM wich dont work with an sigaction(SEGV) */ 260*cdf0e10cSrcweir if ((bSetSEGVHandler || Signals[i].Signal != SIGSEGV) 261*cdf0e10cSrcweir && (bSetWINCHHandler || Signals[i].Signal != SIGWINCH) 262*cdf0e10cSrcweir && (bSetILLHandler || Signals[i].Signal != SIGILL)) 263*cdf0e10cSrcweir { 264*cdf0e10cSrcweir if (Signals[i].Action != ACT_SYSTEM) 265*cdf0e10cSrcweir { 266*cdf0e10cSrcweir if (Signals[i].Action == ACT_HIDE) 267*cdf0e10cSrcweir { 268*cdf0e10cSrcweir struct sigaction ign; 269*cdf0e10cSrcweir 270*cdf0e10cSrcweir ign.sa_handler = SIG_IGN; 271*cdf0e10cSrcweir ign.sa_flags = 0; 272*cdf0e10cSrcweir sigemptyset(&ign.sa_mask); 273*cdf0e10cSrcweir 274*cdf0e10cSrcweir if (sigaction(Signals[i].Signal, &ign, &oact) == 0) 275*cdf0e10cSrcweir Signals[i].Handler = oact.sa_handler; 276*cdf0e10cSrcweir else 277*cdf0e10cSrcweir Signals[i].Handler = SIG_DFL; 278*cdf0e10cSrcweir } 279*cdf0e10cSrcweir else 280*cdf0e10cSrcweir if (sigaction(Signals[i].Signal, &act, &oact) == 0) 281*cdf0e10cSrcweir Signals[i].Handler = oact.sa_handler; 282*cdf0e10cSrcweir else 283*cdf0e10cSrcweir Signals[i].Handler = SIG_DFL; 284*cdf0e10cSrcweir } 285*cdf0e10cSrcweir } 286*cdf0e10cSrcweir } 287*cdf0e10cSrcweir 288*cdf0e10cSrcweir /* Clear signal mask inherited from parent process (on Mac OS X, upon a 289*cdf0e10cSrcweir crash soffice re-execs itself from within the signal handler, so the 290*cdf0e10cSrcweir second soffice would have the guilty signal blocked and would freeze upon 291*cdf0e10cSrcweir encountering a similar crash again): */ 292*cdf0e10cSrcweir if (sigemptyset(&unset) < 0 || 293*cdf0e10cSrcweir pthread_sigmask(SIG_SETMASK, &unset, NULL) < 0) 294*cdf0e10cSrcweir { 295*cdf0e10cSrcweir OSL_TRACE("sigemptyset or pthread_sigmask failed"); 296*cdf0e10cSrcweir } 297*cdf0e10cSrcweir 298*cdf0e10cSrcweir return sal_True; 299*cdf0e10cSrcweir } 300*cdf0e10cSrcweir 301*cdf0e10cSrcweir static sal_Bool DeInitSignal() 302*cdf0e10cSrcweir { 303*cdf0e10cSrcweir int i; 304*cdf0e10cSrcweir struct sigaction act; 305*cdf0e10cSrcweir 306*cdf0e10cSrcweir act.sa_flags = 0; 307*cdf0e10cSrcweir sigemptyset(&(act.sa_mask)); 308*cdf0e10cSrcweir 309*cdf0e10cSrcweir /* Initialize the rest of the signals */ 310*cdf0e10cSrcweir for (i = NoSignals - 1; i >= 0; i--) 311*cdf0e10cSrcweir if (Signals[i].Action != ACT_SYSTEM) 312*cdf0e10cSrcweir { 313*cdf0e10cSrcweir act.sa_handler = Signals[i].Handler; 314*cdf0e10cSrcweir 315*cdf0e10cSrcweir sigaction(Signals[i].Signal, &act, NULL); 316*cdf0e10cSrcweir } 317*cdf0e10cSrcweir 318*cdf0e10cSrcweir osl_destroyMutex(SignalListMutex); 319*cdf0e10cSrcweir 320*cdf0e10cSrcweir return sal_False; 321*cdf0e10cSrcweir } 322*cdf0e10cSrcweir 323*cdf0e10cSrcweir #if defined (SAL_ENABLE_CRASH_REPORT) && defined(INCLUDE_BACKTRACE) 324*cdf0e10cSrcweir 325*cdf0e10cSrcweir /*****************************************************************************/ 326*cdf0e10cSrcweir /* Generate MD5 checksum */ 327*cdf0e10cSrcweir /*****************************************************************************/ 328*cdf0e10cSrcweir 329*cdf0e10cSrcweir static sal_uInt32 calc_md5_checksum( const char *filename, sal_uInt8 *pChecksum, sal_uInt32 nChecksumLen ) 330*cdf0e10cSrcweir { 331*cdf0e10cSrcweir sal_uInt32 nBytesProcessed = 0; 332*cdf0e10cSrcweir 333*cdf0e10cSrcweir FILE *fp = fopen( filename, "r" ); 334*cdf0e10cSrcweir 335*cdf0e10cSrcweir if ( fp ) 336*cdf0e10cSrcweir { 337*cdf0e10cSrcweir rtlDigest digest = rtl_digest_createMD5(); 338*cdf0e10cSrcweir 339*cdf0e10cSrcweir if ( digest ) 340*cdf0e10cSrcweir { 341*cdf0e10cSrcweir size_t nBytesRead; 342*cdf0e10cSrcweir sal_uInt8 buffer[4096]; 343*cdf0e10cSrcweir rtlDigestError error = rtl_Digest_E_None; 344*cdf0e10cSrcweir 345*cdf0e10cSrcweir while ( rtl_Digest_E_None == error && 346*cdf0e10cSrcweir 0 != (nBytesRead = fread( buffer, 1, sizeof(buffer), fp )) ) 347*cdf0e10cSrcweir { 348*cdf0e10cSrcweir error = rtl_digest_updateMD5( digest, buffer, nBytesRead ); 349*cdf0e10cSrcweir nBytesProcessed += nBytesRead; 350*cdf0e10cSrcweir } 351*cdf0e10cSrcweir 352*cdf0e10cSrcweir if ( rtl_Digest_E_None == error ) 353*cdf0e10cSrcweir { 354*cdf0e10cSrcweir error = rtl_digest_getMD5( digest, pChecksum, nChecksumLen ); 355*cdf0e10cSrcweir } 356*cdf0e10cSrcweir 357*cdf0e10cSrcweir if ( rtl_Digest_E_None != error ) 358*cdf0e10cSrcweir nBytesProcessed = 0; 359*cdf0e10cSrcweir 360*cdf0e10cSrcweir rtl_digest_destroyMD5( digest ); 361*cdf0e10cSrcweir } 362*cdf0e10cSrcweir 363*cdf0e10cSrcweir fclose( fp ); 364*cdf0e10cSrcweir } 365*cdf0e10cSrcweir 366*cdf0e10cSrcweir return nBytesProcessed; 367*cdf0e10cSrcweir } 368*cdf0e10cSrcweir 369*cdf0e10cSrcweir /*****************************************************************************/ 370*cdf0e10cSrcweir /* Call crash reporter */ 371*cdf0e10cSrcweir /*****************************************************************************/ 372*cdf0e10cSrcweir 373*cdf0e10cSrcweir /* Helper function to encode and write a string to a stream */ 374*cdf0e10cSrcweir 375*cdf0e10cSrcweir static int fputs_xml( const char *string, FILE *stream ) 376*cdf0e10cSrcweir { 377*cdf0e10cSrcweir int result = 0; 378*cdf0e10cSrcweir 379*cdf0e10cSrcweir while ( result >= 0 && *string ) 380*cdf0e10cSrcweir { 381*cdf0e10cSrcweir switch( *string ) 382*cdf0e10cSrcweir { 383*cdf0e10cSrcweir case '&': 384*cdf0e10cSrcweir result = fputs( "&", stream ); 385*cdf0e10cSrcweir break; 386*cdf0e10cSrcweir case '<': 387*cdf0e10cSrcweir result = fputs( "<", stream ); 388*cdf0e10cSrcweir break; 389*cdf0e10cSrcweir case '>': 390*cdf0e10cSrcweir result = fputs( ">", stream ); 391*cdf0e10cSrcweir break; 392*cdf0e10cSrcweir default: 393*cdf0e10cSrcweir result = fputc( *string, stream ); 394*cdf0e10cSrcweir break; 395*cdf0e10cSrcweir } 396*cdf0e10cSrcweir 397*cdf0e10cSrcweir string++; 398*cdf0e10cSrcweir } 399*cdf0e10cSrcweir 400*cdf0e10cSrcweir return result; 401*cdf0e10cSrcweir } 402*cdf0e10cSrcweir #endif 403*cdf0e10cSrcweir 404*cdf0e10cSrcweir /* Create intermediate files and run crash reporter */ 405*cdf0e10cSrcweir 406*cdf0e10cSrcweir #define REPORTENV_PARAM "-crashreportenv:" 407*cdf0e10cSrcweir 408*cdf0e10cSrcweir #if defined SAL_ENABLE_CRASH_REPORT && defined INCLUDE_BACKTRACE && \ 409*cdf0e10cSrcweir defined LINUX 410*cdf0e10cSrcweir 411*cdf0e10cSrcweir typedef struct 412*cdf0e10cSrcweir { 413*cdf0e10cSrcweir const char *name; 414*cdf0e10cSrcweir ElfW(Off) offset; 415*cdf0e10cSrcweir } dynamic_entry; 416*cdf0e10cSrcweir 417*cdf0e10cSrcweir static int 418*cdf0e10cSrcweir callback(struct dl_phdr_info *info, size_t size, void *data) 419*cdf0e10cSrcweir { 420*cdf0e10cSrcweir const ElfW(Phdr) *pDynamic = NULL; 421*cdf0e10cSrcweir 422*cdf0e10cSrcweir if (size == sizeof(struct dl_phdr_info)) 423*cdf0e10cSrcweir { 424*cdf0e10cSrcweir int i; 425*cdf0e10cSrcweir for (i = 0; i < info->dlpi_phnum; ++i) 426*cdf0e10cSrcweir { 427*cdf0e10cSrcweir if (info->dlpi_phdr[i].p_type == PT_DYNAMIC) 428*cdf0e10cSrcweir { 429*cdf0e10cSrcweir pDynamic = &(info->dlpi_phdr[i]); 430*cdf0e10cSrcweir break; 431*cdf0e10cSrcweir } 432*cdf0e10cSrcweir } 433*cdf0e10cSrcweir } 434*cdf0e10cSrcweir 435*cdf0e10cSrcweir if (pDynamic) 436*cdf0e10cSrcweir { 437*cdf0e10cSrcweir char buffer[100]; 438*cdf0e10cSrcweir int len; 439*cdf0e10cSrcweir char exe[PATH_MAX]; 440*cdf0e10cSrcweir const char *dsoname = info->dlpi_name; 441*cdf0e10cSrcweir 442*cdf0e10cSrcweir dynamic_entry* entry = (dynamic_entry*)data; 443*cdf0e10cSrcweir 444*cdf0e10cSrcweir if (strcmp(dsoname, "") == 0) 445*cdf0e10cSrcweir { 446*cdf0e10cSrcweir snprintf(buffer, sizeof(buffer), "/proc/%d/exe", getpid()); 447*cdf0e10cSrcweir if ((len = readlink(buffer, exe, PATH_MAX)) != -1) 448*cdf0e10cSrcweir { 449*cdf0e10cSrcweir exe[len] = '\0'; 450*cdf0e10cSrcweir dsoname = exe; 451*cdf0e10cSrcweir } 452*cdf0e10cSrcweir } 453*cdf0e10cSrcweir 454*cdf0e10cSrcweir if (strcmp(dsoname, entry->name) == 0) 455*cdf0e10cSrcweir { 456*cdf0e10cSrcweir entry->offset = pDynamic->p_offset; 457*cdf0e10cSrcweir return 1; 458*cdf0e10cSrcweir } 459*cdf0e10cSrcweir } 460*cdf0e10cSrcweir return 0; 461*cdf0e10cSrcweir } 462*cdf0e10cSrcweir 463*cdf0e10cSrcweir /* Get the location of the .dynamic section offset for the given elf file. 464*cdf0e10cSrcweir * i.e. same as the "Offset" value shown for DYNAMIC from readelf -l foo 465*cdf0e10cSrcweir * 466*cdf0e10cSrcweir * We want to know this value so that if the binaries have been modifed 467*cdf0e10cSrcweir * by prelink then we can still process the call stack on server side 468*cdf0e10cSrcweir * by comparing this value to that of an "un-prelinked but known to be 469*cdf0e10cSrcweir * otherwise equivalent" version of those binaries and adjust the call 470*cdf0e10cSrcweir * stack addresses by the differences between .dynamic addresses so as 471*cdf0e10cSrcweir * to be able to map the prelinked addresses back to the unprelinked 472*cdf0e10cSrcweir * addresses 473*cdf0e10cSrcweir * 474*cdf0e10cSrcweir * cmc@openoffice.org 475*cdf0e10cSrcweir */ 476*cdf0e10cSrcweir static ElfW(Off) 477*cdf0e10cSrcweir dynamic_section_offset(const char *name) 478*cdf0e10cSrcweir { 479*cdf0e10cSrcweir dynamic_entry entry; 480*cdf0e10cSrcweir 481*cdf0e10cSrcweir entry.name = name; 482*cdf0e10cSrcweir entry.offset = 0; 483*cdf0e10cSrcweir 484*cdf0e10cSrcweir dl_iterate_phdr(callback, &entry); 485*cdf0e10cSrcweir 486*cdf0e10cSrcweir return entry.offset; 487*cdf0e10cSrcweir } 488*cdf0e10cSrcweir #endif 489*cdf0e10cSrcweir 490*cdf0e10cSrcweir static int ReportCrash( int Signal ) 491*cdf0e10cSrcweir { 492*cdf0e10cSrcweir #ifdef SAL_ENABLE_CRASH_REPORT 493*cdf0e10cSrcweir static sal_Bool bCrashReporterExecuted = sal_False; 494*cdf0e10cSrcweir sal_Bool bAutoCrashReport = sal_False; 495*cdf0e10cSrcweir 496*cdf0e10cSrcweir sal_uInt32 argi; 497*cdf0e10cSrcweir sal_uInt32 argc; 498*cdf0e10cSrcweir rtl_uString *ustrCommandArg = NULL; 499*cdf0e10cSrcweir 500*cdf0e10cSrcweir if ( !bErrorReportingEnabled ) 501*cdf0e10cSrcweir return -1; 502*cdf0e10cSrcweir 503*cdf0e10cSrcweir argc = osl_getCommandArgCount(); 504*cdf0e10cSrcweir 505*cdf0e10cSrcweir for ( argi = 0; argi < argc; argi++ ) 506*cdf0e10cSrcweir { 507*cdf0e10cSrcweir if ( osl_Process_E_None == osl_getCommandArg( argi, &ustrCommandArg ) ) 508*cdf0e10cSrcweir { 509*cdf0e10cSrcweir if ( 0 == rtl_ustr_ascii_compare( rtl_uString_getStr( ustrCommandArg ), "-nocrashreport" ) ) 510*cdf0e10cSrcweir { 511*cdf0e10cSrcweir rtl_uString_release( ustrCommandArg ); 512*cdf0e10cSrcweir return -1; 513*cdf0e10cSrcweir } 514*cdf0e10cSrcweir else if ( 0 == rtl_ustr_ascii_compare( rtl_uString_getStr( ustrCommandArg ), "-autocrashreport" ) ) 515*cdf0e10cSrcweir { 516*cdf0e10cSrcweir bAutoCrashReport = sal_True; 517*cdf0e10cSrcweir } 518*cdf0e10cSrcweir else if ( 0 == rtl_ustr_ascii_shortenedCompare_WithLength( 519*cdf0e10cSrcweir rtl_uString_getStr( ustrCommandArg ), rtl_uString_getLength( ustrCommandArg ), 520*cdf0e10cSrcweir REPORTENV_PARAM, strlen(REPORTENV_PARAM) ) 521*cdf0e10cSrcweir ) 522*cdf0e10cSrcweir { 523*cdf0e10cSrcweir rtl_uString *ustrEnvironment = NULL; 524*cdf0e10cSrcweir rtl_String *strEnv = NULL; 525*cdf0e10cSrcweir 526*cdf0e10cSrcweir rtl_uString_newFromStr( &ustrEnvironment, rtl_uString_getStr( ustrCommandArg ) + strlen(REPORTENV_PARAM) ); 527*cdf0e10cSrcweir 528*cdf0e10cSrcweir if ( ustrEnvironment ) 529*cdf0e10cSrcweir { 530*cdf0e10cSrcweir rtl_uString2String( 531*cdf0e10cSrcweir &strEnv, 532*cdf0e10cSrcweir rtl_uString_getStr( ustrEnvironment ), rtl_uString_getLength( ustrEnvironment ), 533*cdf0e10cSrcweir osl_getThreadTextEncoding(), OUSTRING_TO_OSTRING_CVTFLAGS 534*cdf0e10cSrcweir ); 535*cdf0e10cSrcweir 536*cdf0e10cSrcweir if ( strEnv ) 537*cdf0e10cSrcweir { 538*cdf0e10cSrcweir putenv( rtl_string_getStr( strEnv ) ); 539*cdf0e10cSrcweir rtl_string_release( strEnv ); 540*cdf0e10cSrcweir } 541*cdf0e10cSrcweir 542*cdf0e10cSrcweir rtl_uString_release( ustrEnvironment ); 543*cdf0e10cSrcweir } 544*cdf0e10cSrcweir 545*cdf0e10cSrcweir } 546*cdf0e10cSrcweir 547*cdf0e10cSrcweir } 548*cdf0e10cSrcweir } 549*cdf0e10cSrcweir 550*cdf0e10cSrcweir if ( ustrCommandArg ) 551*cdf0e10cSrcweir rtl_uString_release( ustrCommandArg ); 552*cdf0e10cSrcweir 553*cdf0e10cSrcweir if ( !bCrashReporterExecuted ) 554*cdf0e10cSrcweir { 555*cdf0e10cSrcweir int i; 556*cdf0e10cSrcweir /* struct sigaction act; */ 557*cdf0e10cSrcweir 558*cdf0e10cSrcweir for (i = 0; i < NoSignals; i++) 559*cdf0e10cSrcweir { 560*cdf0e10cSrcweir if (Signals[i].Signal == Signal && Signals[i].Action == ACT_ABORT ) 561*cdf0e10cSrcweir { 562*cdf0e10cSrcweir int ret; 563*cdf0e10cSrcweir char szShellCmd[512] = { '\0' }; 564*cdf0e10cSrcweir char *pXMLTempName = NULL; 565*cdf0e10cSrcweir char *pStackTempName = NULL; 566*cdf0e10cSrcweir char *pChecksumTempName = NULL; 567*cdf0e10cSrcweir 568*cdf0e10cSrcweir #ifdef INCLUDE_BACKTRACE 569*cdf0e10cSrcweir char szXMLTempNameBuffer[L_tmpnam]; 570*cdf0e10cSrcweir char szChecksumTempNameBuffer[L_tmpnam]; 571*cdf0e10cSrcweir char szStackTempNameBuffer[L_tmpnam]; 572*cdf0e10cSrcweir 573*cdf0e10cSrcweir void *stackframes[MAX_STACK_FRAMES]; 574*cdf0e10cSrcweir int iFrame; 575*cdf0e10cSrcweir int nFrames = backtrace( stackframes, sizeof(stackframes)/sizeof(stackframes[0])); 576*cdf0e10cSrcweir 577*cdf0e10cSrcweir FILE *xmlout = NULL, *stackout = NULL, *checksumout = NULL; 578*cdf0e10cSrcweir int fdxml, fdstk, fdchksum; 579*cdf0e10cSrcweir 580*cdf0e10cSrcweir strncpy( szXMLTempNameBuffer, P_tmpdir, sizeof(szXMLTempNameBuffer) ); 581*cdf0e10cSrcweir strncat( szXMLTempNameBuffer, "/crxmlXXXXXX", sizeof(szXMLTempNameBuffer) ); 582*cdf0e10cSrcweir 583*cdf0e10cSrcweir strncpy( szStackTempNameBuffer, P_tmpdir, sizeof(szStackTempNameBuffer) ); 584*cdf0e10cSrcweir strncat( szStackTempNameBuffer, "/crstkXXXXXX", sizeof(szStackTempNameBuffer) ); 585*cdf0e10cSrcweir 586*cdf0e10cSrcweir strncpy( szChecksumTempNameBuffer, P_tmpdir, sizeof(szChecksumTempNameBuffer) ); 587*cdf0e10cSrcweir strncat( szChecksumTempNameBuffer, "/crchkXXXXXX", sizeof(szChecksumTempNameBuffer) ); 588*cdf0e10cSrcweir 589*cdf0e10cSrcweir fdxml = mkstemp(szXMLTempNameBuffer); 590*cdf0e10cSrcweir fdstk = mkstemp(szStackTempNameBuffer); 591*cdf0e10cSrcweir fdchksum = mkstemp(szChecksumTempNameBuffer); 592*cdf0e10cSrcweir 593*cdf0e10cSrcweir xmlout = fdopen( fdxml , "w" ); 594*cdf0e10cSrcweir stackout = fdopen( fdstk , "w" ); 595*cdf0e10cSrcweir checksumout = fdopen( fdchksum, "w" ); 596*cdf0e10cSrcweir 597*cdf0e10cSrcweir pXMLTempName = szXMLTempNameBuffer; 598*cdf0e10cSrcweir pStackTempName = szStackTempNameBuffer; 599*cdf0e10cSrcweir pChecksumTempName = szChecksumTempNameBuffer; 600*cdf0e10cSrcweir 601*cdf0e10cSrcweir 602*cdf0e10cSrcweir if ( xmlout && stackout && checksumout ) 603*cdf0e10cSrcweir { 604*cdf0e10cSrcweir fprintf( xmlout, "<errormail:Stack type=\"%s\">\n", STACKTYPE ); 605*cdf0e10cSrcweir 606*cdf0e10cSrcweir fprintf( checksumout, "<errormail:Checksums type=\"MD5\">\n" ); 607*cdf0e10cSrcweir 608*cdf0e10cSrcweir for ( iFrame = 0; iFrame < nFrames; iFrame++ ) 609*cdf0e10cSrcweir { 610*cdf0e10cSrcweir Dl_info dl_info; 611*cdf0e10cSrcweir 612*cdf0e10cSrcweir fprintf( stackout, "0x%" SAL_PRIxUINTPTR ":", 613*cdf0e10cSrcweir SAL_INT_CAST(sal_uIntPtr, stackframes[iFrame]) ); 614*cdf0e10cSrcweir 615*cdf0e10cSrcweir fprintf( xmlout, "<errormail:StackInfo pos=\"%d\" ip=\"0x%" SAL_PRIxUINTPTR "\"", 616*cdf0e10cSrcweir iFrame, 617*cdf0e10cSrcweir SAL_INT_CAST(sal_uIntPtr, stackframes[iFrame]) 618*cdf0e10cSrcweir ); 619*cdf0e10cSrcweir 620*cdf0e10cSrcweir memset( &dl_info, 0, sizeof(dl_info) ); 621*cdf0e10cSrcweir 622*cdf0e10cSrcweir /* dladdr may fail */ 623*cdf0e10cSrcweir if ( dladdr( stackframes[iFrame], &dl_info) ) 624*cdf0e10cSrcweir { 625*cdf0e10cSrcweir const char *dli_fname = NULL; 626*cdf0e10cSrcweir char *dli_fdir = NULL; 627*cdf0e10cSrcweir char szDirectory[PATH_MAX]; 628*cdf0e10cSrcweir char szCanonicDirectory[PATH_MAX]; 629*cdf0e10cSrcweir 630*cdf0e10cSrcweir /* Don't expect that dladdr filled all members of dl_info */ 631*cdf0e10cSrcweir 632*cdf0e10cSrcweir dli_fname = dl_info.dli_fname ? strrchr( dl_info.dli_fname, '/' ) : NULL; 633*cdf0e10cSrcweir if ( dli_fname ) 634*cdf0e10cSrcweir { 635*cdf0e10cSrcweir ++dli_fname; 636*cdf0e10cSrcweir memcpy( szDirectory, dl_info.dli_fname, dli_fname - dl_info.dli_fname ); 637*cdf0e10cSrcweir szDirectory[dli_fname - dl_info.dli_fname] = 0; 638*cdf0e10cSrcweir 639*cdf0e10cSrcweir dli_fdir = realpath( szDirectory, szCanonicDirectory ) ? szCanonicDirectory : szDirectory; 640*cdf0e10cSrcweir 641*cdf0e10cSrcweir if ( *dli_fdir && dli_fdir[ strlen(dli_fdir) - 1 ] != '/' ) 642*cdf0e10cSrcweir strcat( dli_fdir, "/" ); 643*cdf0e10cSrcweir } 644*cdf0e10cSrcweir else 645*cdf0e10cSrcweir dli_fname = dl_info.dli_fname; 646*cdf0e10cSrcweir 647*cdf0e10cSrcweir /* create checksum of library on stack */ 648*cdf0e10cSrcweir if ( dli_fname ) 649*cdf0e10cSrcweir { 650*cdf0e10cSrcweir sal_uInt8 checksum[RTL_DIGEST_LENGTH_MD5]; 651*cdf0e10cSrcweir 652*cdf0e10cSrcweir sal_uInt32 nBytesProcessed = calc_md5_checksum( 653*cdf0e10cSrcweir dl_info.dli_fname, checksum, sizeof(checksum) ); 654*cdf0e10cSrcweir if ( nBytesProcessed ) 655*cdf0e10cSrcweir { 656*cdf0e10cSrcweir int j; 657*cdf0e10cSrcweir 658*cdf0e10cSrcweir fprintf( checksumout, "<errormail:Checksum sum=\"0x" ); 659*cdf0e10cSrcweir for ( j = 0; j < 16; fprintf( checksumout, "%02X", checksum[j++] ) ); 660*cdf0e10cSrcweir fprintf( checksumout, 661*cdf0e10cSrcweir "\" bytes=\"%lu\" file=\"%s\"/>\n", 662*cdf0e10cSrcweir SAL_INT_CAST( 663*cdf0e10cSrcweir unsigned long, nBytesProcessed), 664*cdf0e10cSrcweir dli_fname ); 665*cdf0e10cSrcweir } 666*cdf0e10cSrcweir } 667*cdf0e10cSrcweir 668*cdf0e10cSrcweir if ( dl_info.dli_fbase && dl_info.dli_fname ) 669*cdf0e10cSrcweir { 670*cdf0e10cSrcweir #ifdef LINUX 671*cdf0e10cSrcweir ElfW(Off) dynamic_offset = dynamic_section_offset(dl_info.dli_fname); 672*cdf0e10cSrcweir fprintf( stackout, " 0x%" SAL_PRI_SIZET "x:", dynamic_offset); 673*cdf0e10cSrcweir #endif 674*cdf0e10cSrcweir 675*cdf0e10cSrcweir fprintf( stackout, " %s + 0x%" SAL_PRI_PTRDIFFT "x", 676*cdf0e10cSrcweir dl_info.dli_fname, 677*cdf0e10cSrcweir (char*)stackframes[iFrame] - (char*)dl_info.dli_fbase 678*cdf0e10cSrcweir ); 679*cdf0e10cSrcweir 680*cdf0e10cSrcweir fprintf( xmlout, " rel=\"0x%" SAL_PRI_PTRDIFFT "x\"", (char *)stackframes[iFrame] - (char *)dl_info.dli_fbase ); 681*cdf0e10cSrcweir if ( dli_fname ) 682*cdf0e10cSrcweir fprintf( xmlout, " name=\"%s\"", dli_fname ); 683*cdf0e10cSrcweir 684*cdf0e10cSrcweir if ( dli_fdir ) 685*cdf0e10cSrcweir fprintf( xmlout, " path=\"%s\"", dli_fdir ); 686*cdf0e10cSrcweir 687*cdf0e10cSrcweir #ifdef LINUX 688*cdf0e10cSrcweir fprintf( xmlout, " dynamicoffset=\"0x%" SAL_PRI_SIZET "x\"", dynamic_offset ); 689*cdf0e10cSrcweir #endif 690*cdf0e10cSrcweir } 691*cdf0e10cSrcweir else 692*cdf0e10cSrcweir fprintf( stackout, " ????????" ); 693*cdf0e10cSrcweir 694*cdf0e10cSrcweir if ( dl_info.dli_sname && dl_info.dli_saddr ) 695*cdf0e10cSrcweir { 696*cdf0e10cSrcweir fputs( " (", stackout ); 697*cdf0e10cSrcweir fputs_xml( dl_info.dli_sname, stackout ); 698*cdf0e10cSrcweir fprintf( stackout, " + 0x%" SAL_PRI_PTRDIFFT "x)", 699*cdf0e10cSrcweir (char*)stackframes[iFrame] - (char*)dl_info.dli_saddr ); 700*cdf0e10cSrcweir 701*cdf0e10cSrcweir fputs( " ordinal=\"", xmlout ); 702*cdf0e10cSrcweir fputs_xml( dl_info.dli_sname, xmlout ); 703*cdf0e10cSrcweir fprintf( xmlout, "+0x%" SAL_PRI_PTRDIFFT "x\"", 704*cdf0e10cSrcweir (char *)stackframes[iFrame] - (char *)dl_info.dli_saddr ); 705*cdf0e10cSrcweir } 706*cdf0e10cSrcweir 707*cdf0e10cSrcweir } 708*cdf0e10cSrcweir else /* dladdr failed */ 709*cdf0e10cSrcweir { 710*cdf0e10cSrcweir fprintf( stackout, " ????????" ); 711*cdf0e10cSrcweir } 712*cdf0e10cSrcweir 713*cdf0e10cSrcweir fprintf( stackout, "\n" ); 714*cdf0e10cSrcweir fprintf( xmlout, "/>\n" ); 715*cdf0e10cSrcweir 716*cdf0e10cSrcweir } 717*cdf0e10cSrcweir 718*cdf0e10cSrcweir fprintf( xmlout, "</errormail:Stack>\n" ); 719*cdf0e10cSrcweir fprintf( checksumout, "</errormail:Checksums>\n" ); 720*cdf0e10cSrcweir } 721*cdf0e10cSrcweir else 722*cdf0e10cSrcweir { 723*cdf0e10cSrcweir pXMLTempName = NULL; 724*cdf0e10cSrcweir pStackTempName = NULL; 725*cdf0e10cSrcweir pChecksumTempName = NULL; 726*cdf0e10cSrcweir } 727*cdf0e10cSrcweir 728*cdf0e10cSrcweir if ( stackout ) 729*cdf0e10cSrcweir fclose( stackout ); 730*cdf0e10cSrcweir if ( xmlout ) 731*cdf0e10cSrcweir fclose( xmlout ); 732*cdf0e10cSrcweir if ( checksumout ) 733*cdf0e10cSrcweir fclose( checksumout ); 734*cdf0e10cSrcweir 735*cdf0e10cSrcweir if ( pXMLTempName && pChecksumTempName && pStackTempName ) 736*cdf0e10cSrcweir #endif /* INCLUDE_BACKTRACE */ 737*cdf0e10cSrcweir { 738*cdf0e10cSrcweir rtl_uString * crashrep_url = NULL; 739*cdf0e10cSrcweir rtl_uString * crashrep_path = NULL; 740*cdf0e10cSrcweir rtl_String * crashrep_path_system = NULL; 741*cdf0e10cSrcweir rtl_string2UString( 742*cdf0e10cSrcweir &crashrep_url, 743*cdf0e10cSrcweir RTL_CONSTASCII_USTRINGPARAM( 744*cdf0e10cSrcweir "$BRAND_BASE_DIR/program/crashrep"), 745*cdf0e10cSrcweir OSTRING_TO_OUSTRING_CVTFLAGS); 746*cdf0e10cSrcweir rtl_bootstrap_expandMacros(&crashrep_url); 747*cdf0e10cSrcweir osl_getSystemPathFromFileURL(crashrep_url, &crashrep_path); 748*cdf0e10cSrcweir rtl_uString2String( 749*cdf0e10cSrcweir &crashrep_path_system, 750*cdf0e10cSrcweir rtl_uString_getStr(crashrep_path), 751*cdf0e10cSrcweir rtl_uString_getLength(crashrep_path), 752*cdf0e10cSrcweir osl_getThreadTextEncoding(), 753*cdf0e10cSrcweir (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR 754*cdf0e10cSrcweir | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)); 755*cdf0e10cSrcweir rtl_uString_release(crashrep_url); 756*cdf0e10cSrcweir rtl_uString_release(crashrep_path); 757*cdf0e10cSrcweir #if defined INCLUDE_BACKTRACE && (defined LINUX || defined MACOSX) 758*cdf0e10cSrcweir snprintf( szShellCmd, sizeof(szShellCmd)/sizeof(szShellCmd[0]), 759*cdf0e10cSrcweir "%s -p %d -s %d -xml %s -chksum %s -stack %s -noui%s", 760*cdf0e10cSrcweir rtl_string_getStr(crashrep_path_system), 761*cdf0e10cSrcweir getpid(), 762*cdf0e10cSrcweir Signal, 763*cdf0e10cSrcweir pXMLTempName, 764*cdf0e10cSrcweir pChecksumTempName, 765*cdf0e10cSrcweir pStackTempName, 766*cdf0e10cSrcweir bAutoCrashReport ? " -send" : "" ); 767*cdf0e10cSrcweir #elif defined INCLUDE_BACKTRACE && defined SOLARIS 768*cdf0e10cSrcweir snprintf( szShellCmd, sizeof(szShellCmd)/sizeof(szShellCmd[0]), 769*cdf0e10cSrcweir "%s -p %d -s %d -xml %s -chksum %s -noui%s", 770*cdf0e10cSrcweir rtl_string_getStr(crashrep_path_system), 771*cdf0e10cSrcweir getpid(), 772*cdf0e10cSrcweir Signal, 773*cdf0e10cSrcweir pXMLTempName, 774*cdf0e10cSrcweir pChecksumTempName, 775*cdf0e10cSrcweir bAutoCrashReport ? " -send" : "" ); 776*cdf0e10cSrcweir #else 777*cdf0e10cSrcweir snprintf( szShellCmd, sizeof(szShellCmd)/sizeof(szShellCmd[0]), 778*cdf0e10cSrcweir "%s -p %d -s %d -noui%s", 779*cdf0e10cSrcweir rtl_string_getStr(crashrep_path_system), 780*cdf0e10cSrcweir getpid(), Signal, bAutoCrashReport ? " -send" : "" ); 781*cdf0e10cSrcweir #endif 782*cdf0e10cSrcweir rtl_string_release(crashrep_path_system); 783*cdf0e10cSrcweir } 784*cdf0e10cSrcweir 785*cdf0e10cSrcweir ret = szShellCmd[0] == '\0' ? -1 : system( szShellCmd ); 786*cdf0e10cSrcweir 787*cdf0e10cSrcweir if ( pXMLTempName ) 788*cdf0e10cSrcweir unlink( pXMLTempName ); 789*cdf0e10cSrcweir 790*cdf0e10cSrcweir if ( pStackTempName ) 791*cdf0e10cSrcweir unlink( pStackTempName ); 792*cdf0e10cSrcweir 793*cdf0e10cSrcweir if ( pChecksumTempName ) 794*cdf0e10cSrcweir unlink( pChecksumTempName ); 795*cdf0e10cSrcweir 796*cdf0e10cSrcweir if ( -1 != ret ) 797*cdf0e10cSrcweir { 798*cdf0e10cSrcweir bCrashReporterExecuted = sal_True; 799*cdf0e10cSrcweir return 1; 800*cdf0e10cSrcweir } 801*cdf0e10cSrcweir else 802*cdf0e10cSrcweir return -1; 803*cdf0e10cSrcweir 804*cdf0e10cSrcweir } 805*cdf0e10cSrcweir } 806*cdf0e10cSrcweir 807*cdf0e10cSrcweir return 0; 808*cdf0e10cSrcweir } 809*cdf0e10cSrcweir 810*cdf0e10cSrcweir return 1; 811*cdf0e10cSrcweir #else /* defined SAL_ENABLE_CRASH_REPORT */ 812*cdf0e10cSrcweir /* the utility crash_report is not build, so do the same as when 813*cdf0e10cSrcweir the option -nocrashreport is used */ 814*cdf0e10cSrcweir (void) Signal; // avoid warnings 815*cdf0e10cSrcweir return -1; 816*cdf0e10cSrcweir #endif /* defined SAL_ENABLE_CRASH_REPORT */ 817*cdf0e10cSrcweir } 818*cdf0e10cSrcweir 819*cdf0e10cSrcweir static void PrintStack( int sig ) 820*cdf0e10cSrcweir { 821*cdf0e10cSrcweir #if ! defined(MACOSX) || defined(INCLUDE_BACKTRACE) 822*cdf0e10cSrcweir void *buffer[MAX_STACK_FRAMES]; 823*cdf0e10cSrcweir int size = backtrace( buffer, sizeof(buffer) / sizeof(buffer[0]) ); 824*cdf0e10cSrcweir #endif 825*cdf0e10cSrcweir 826*cdf0e10cSrcweir fprintf( stderr, "\n\nFatal exception: Signal %d\n", sig ); 827*cdf0e10cSrcweir 828*cdf0e10cSrcweir #if defined(MACOSX) && ! defined(INCLUDE_BACKTRACE) 829*cdf0e10cSrcweir fprintf( stderr, "Please turn on Enable Crash Reporting and\nAutomatic Display of Crashlogs in the Console application\n" ); 830*cdf0e10cSrcweir #else 831*cdf0e10cSrcweir if ( size > 0 ) 832*cdf0e10cSrcweir { 833*cdf0e10cSrcweir fputs( "Stack:\n", stderr ); 834*cdf0e10cSrcweir backtrace_symbols_fd( buffer, size, fileno(stderr) ); 835*cdf0e10cSrcweir } 836*cdf0e10cSrcweir #endif 837*cdf0e10cSrcweir } 838*cdf0e10cSrcweir 839*cdf0e10cSrcweir static oslSignalAction CallSignalHandler(oslSignalInfo *pInfo) 840*cdf0e10cSrcweir { 841*cdf0e10cSrcweir oslSignalHandlerImpl* pHandler = SignalList; 842*cdf0e10cSrcweir oslSignalAction Action = osl_Signal_ActCallNextHdl; 843*cdf0e10cSrcweir 844*cdf0e10cSrcweir while (pHandler != NULL) 845*cdf0e10cSrcweir { 846*cdf0e10cSrcweir if ((Action = pHandler->Handler(pHandler->pData, pInfo)) 847*cdf0e10cSrcweir != osl_Signal_ActCallNextHdl) 848*cdf0e10cSrcweir break; 849*cdf0e10cSrcweir 850*cdf0e10cSrcweir pHandler = pHandler->pNext; 851*cdf0e10cSrcweir } 852*cdf0e10cSrcweir 853*cdf0e10cSrcweir return Action; 854*cdf0e10cSrcweir } 855*cdf0e10cSrcweir 856*cdf0e10cSrcweir void CallSystemHandler(int Signal) 857*cdf0e10cSrcweir { 858*cdf0e10cSrcweir int i; 859*cdf0e10cSrcweir struct sigaction act; 860*cdf0e10cSrcweir 861*cdf0e10cSrcweir for (i = 0; i < NoSignals; i++) 862*cdf0e10cSrcweir { 863*cdf0e10cSrcweir if (Signals[i].Signal == Signal) 864*cdf0e10cSrcweir break; 865*cdf0e10cSrcweir } 866*cdf0e10cSrcweir 867*cdf0e10cSrcweir if (i < NoSignals) 868*cdf0e10cSrcweir { 869*cdf0e10cSrcweir if ((Signals[i].Handler == NULL) || 870*cdf0e10cSrcweir (Signals[i].Handler == SIG_DFL) || 871*cdf0e10cSrcweir (Signals[i].Handler == SIG_IGN) || 872*cdf0e10cSrcweir (Signals[i].Handler == SIG_ERR)) 873*cdf0e10cSrcweir { 874*cdf0e10cSrcweir switch (Signals[i].Action) 875*cdf0e10cSrcweir { 876*cdf0e10cSrcweir case ACT_EXIT: /* terminate */ 877*cdf0e10cSrcweir /* prevent dumping core on exit() */ 878*cdf0e10cSrcweir _exit(255); 879*cdf0e10cSrcweir break; 880*cdf0e10cSrcweir 881*cdf0e10cSrcweir case ACT_ABORT: /* terminate witch core dump */ 882*cdf0e10cSrcweir ReportCrash( Signal ); 883*cdf0e10cSrcweir act.sa_handler = SIG_DFL; 884*cdf0e10cSrcweir act.sa_flags = 0; 885*cdf0e10cSrcweir sigemptyset(&(act.sa_mask)); 886*cdf0e10cSrcweir sigaction(SIGABRT, &act, NULL); 887*cdf0e10cSrcweir PrintStack( Signal ); 888*cdf0e10cSrcweir abort(); 889*cdf0e10cSrcweir break; 890*cdf0e10cSrcweir 891*cdf0e10cSrcweir case ACT_IGNORE: /* ignore */ 892*cdf0e10cSrcweir break; 893*cdf0e10cSrcweir 894*cdf0e10cSrcweir default: /* should never happen */ 895*cdf0e10cSrcweir OSL_ASSERT(0); 896*cdf0e10cSrcweir } 897*cdf0e10cSrcweir } 898*cdf0e10cSrcweir else 899*cdf0e10cSrcweir (*Signals[i].Handler)(Signal); 900*cdf0e10cSrcweir } 901*cdf0e10cSrcweir } 902*cdf0e10cSrcweir 903*cdf0e10cSrcweir 904*cdf0e10cSrcweir /*****************************************************************************/ 905*cdf0e10cSrcweir /* SignalHandlerFunction */ 906*cdf0e10cSrcweir /*****************************************************************************/ 907*cdf0e10cSrcweir void SignalHandlerFunction(int Signal) 908*cdf0e10cSrcweir { 909*cdf0e10cSrcweir oslSignalInfo Info; 910*cdf0e10cSrcweir struct sigaction act; 911*cdf0e10cSrcweir 912*cdf0e10cSrcweir Info.UserSignal = Signal; 913*cdf0e10cSrcweir Info.UserData = NULL; 914*cdf0e10cSrcweir 915*cdf0e10cSrcweir switch (Signal) 916*cdf0e10cSrcweir { 917*cdf0e10cSrcweir case SIGBUS: 918*cdf0e10cSrcweir case SIGILL: 919*cdf0e10cSrcweir case SIGSEGV: 920*cdf0e10cSrcweir case SIGIOT: 921*cdf0e10cSrcweir #if ( SIGIOT != SIGABRT ) 922*cdf0e10cSrcweir case SIGABRT: 923*cdf0e10cSrcweir #endif 924*cdf0e10cSrcweir Info.Signal = osl_Signal_AccessViolation; 925*cdf0e10cSrcweir break; 926*cdf0e10cSrcweir 927*cdf0e10cSrcweir case -1: 928*cdf0e10cSrcweir Info.Signal = osl_Signal_IntegerDivideByZero; 929*cdf0e10cSrcweir break; 930*cdf0e10cSrcweir 931*cdf0e10cSrcweir case SIGFPE: 932*cdf0e10cSrcweir Info.Signal = osl_Signal_FloatDivideByZero; 933*cdf0e10cSrcweir break; 934*cdf0e10cSrcweir 935*cdf0e10cSrcweir case SIGINT: 936*cdf0e10cSrcweir case SIGTERM: 937*cdf0e10cSrcweir case SIGQUIT: 938*cdf0e10cSrcweir case SIGHUP: 939*cdf0e10cSrcweir Info.Signal = osl_Signal_Terminate; 940*cdf0e10cSrcweir break; 941*cdf0e10cSrcweir 942*cdf0e10cSrcweir default: 943*cdf0e10cSrcweir Info.Signal = osl_Signal_System; 944*cdf0e10cSrcweir break; 945*cdf0e10cSrcweir } 946*cdf0e10cSrcweir 947*cdf0e10cSrcweir ReportCrash( Signal ); 948*cdf0e10cSrcweir 949*cdf0e10cSrcweir /* Portal Demo HACK !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 950*cdf0e10cSrcweir if (bDoHardKill && (Info.Signal == osl_Signal_AccessViolation)) 951*cdf0e10cSrcweir _exit(255); 952*cdf0e10cSrcweir /* Portal Demo HACK !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ 953*cdf0e10cSrcweir 954*cdf0e10cSrcweir 955*cdf0e10cSrcweir switch (CallSignalHandler(&Info)) 956*cdf0e10cSrcweir { 957*cdf0e10cSrcweir case osl_Signal_ActCallNextHdl: 958*cdf0e10cSrcweir CallSystemHandler(Signal); 959*cdf0e10cSrcweir break; 960*cdf0e10cSrcweir 961*cdf0e10cSrcweir case osl_Signal_ActAbortApp: 962*cdf0e10cSrcweir ReportCrash( Signal ); 963*cdf0e10cSrcweir act.sa_handler = SIG_DFL; 964*cdf0e10cSrcweir act.sa_flags = 0; 965*cdf0e10cSrcweir sigemptyset(&(act.sa_mask)); 966*cdf0e10cSrcweir sigaction(SIGABRT, &act, NULL); 967*cdf0e10cSrcweir PrintStack( Signal ); 968*cdf0e10cSrcweir abort(); 969*cdf0e10cSrcweir break; 970*cdf0e10cSrcweir 971*cdf0e10cSrcweir case osl_Signal_ActKillApp: 972*cdf0e10cSrcweir /* prevent dumping core on exit() */ 973*cdf0e10cSrcweir _exit(255); 974*cdf0e10cSrcweir break; 975*cdf0e10cSrcweir default: 976*cdf0e10cSrcweir break; 977*cdf0e10cSrcweir } 978*cdf0e10cSrcweir } 979*cdf0e10cSrcweir 980*cdf0e10cSrcweir /*****************************************************************************/ 981*cdf0e10cSrcweir /* osl_addSignalHandler */ 982*cdf0e10cSrcweir /*****************************************************************************/ 983*cdf0e10cSrcweir oslSignalHandler SAL_CALL osl_addSignalHandler(oslSignalHandlerFunction Handler, void* pData) 984*cdf0e10cSrcweir { 985*cdf0e10cSrcweir oslSignalHandlerImpl* pHandler; 986*cdf0e10cSrcweir 987*cdf0e10cSrcweir OSL_ASSERT(Handler != NULL); 988*cdf0e10cSrcweir if ( Handler == 0 ) 989*cdf0e10cSrcweir { 990*cdf0e10cSrcweir return 0; 991*cdf0e10cSrcweir } 992*cdf0e10cSrcweir 993*cdf0e10cSrcweir if (! bInitSignal) 994*cdf0e10cSrcweir bInitSignal = InitSignal(); 995*cdf0e10cSrcweir 996*cdf0e10cSrcweir pHandler = (oslSignalHandlerImpl*) calloc(1, sizeof(oslSignalHandlerImpl)); 997*cdf0e10cSrcweir 998*cdf0e10cSrcweir if (pHandler != NULL) 999*cdf0e10cSrcweir { 1000*cdf0e10cSrcweir pHandler->Handler = Handler; 1001*cdf0e10cSrcweir pHandler->pData = pData; 1002*cdf0e10cSrcweir 1003*cdf0e10cSrcweir osl_acquireMutex(SignalListMutex); 1004*cdf0e10cSrcweir 1005*cdf0e10cSrcweir pHandler->pNext = SignalList; 1006*cdf0e10cSrcweir SignalList = pHandler; 1007*cdf0e10cSrcweir 1008*cdf0e10cSrcweir osl_releaseMutex(SignalListMutex); 1009*cdf0e10cSrcweir 1010*cdf0e10cSrcweir return (pHandler); 1011*cdf0e10cSrcweir } 1012*cdf0e10cSrcweir 1013*cdf0e10cSrcweir return (NULL); 1014*cdf0e10cSrcweir } 1015*cdf0e10cSrcweir 1016*cdf0e10cSrcweir /*****************************************************************************/ 1017*cdf0e10cSrcweir /* osl_removeSignalHandler */ 1018*cdf0e10cSrcweir /*****************************************************************************/ 1019*cdf0e10cSrcweir sal_Bool SAL_CALL osl_removeSignalHandler(oslSignalHandler Handler) 1020*cdf0e10cSrcweir { 1021*cdf0e10cSrcweir oslSignalHandlerImpl *pHandler, *pPrevious = NULL; 1022*cdf0e10cSrcweir 1023*cdf0e10cSrcweir OSL_ASSERT(Handler != NULL); 1024*cdf0e10cSrcweir 1025*cdf0e10cSrcweir if (! bInitSignal) 1026*cdf0e10cSrcweir bInitSignal = InitSignal(); 1027*cdf0e10cSrcweir 1028*cdf0e10cSrcweir osl_acquireMutex(SignalListMutex); 1029*cdf0e10cSrcweir 1030*cdf0e10cSrcweir pHandler = SignalList; 1031*cdf0e10cSrcweir 1032*cdf0e10cSrcweir while (pHandler != NULL) 1033*cdf0e10cSrcweir { 1034*cdf0e10cSrcweir if (pHandler == Handler) 1035*cdf0e10cSrcweir { 1036*cdf0e10cSrcweir if (pPrevious) 1037*cdf0e10cSrcweir pPrevious->pNext = pHandler->pNext; 1038*cdf0e10cSrcweir else 1039*cdf0e10cSrcweir SignalList = pHandler->pNext; 1040*cdf0e10cSrcweir 1041*cdf0e10cSrcweir osl_releaseMutex(SignalListMutex); 1042*cdf0e10cSrcweir 1043*cdf0e10cSrcweir if (SignalList == NULL) 1044*cdf0e10cSrcweir bInitSignal = DeInitSignal(); 1045*cdf0e10cSrcweir 1046*cdf0e10cSrcweir free(pHandler); 1047*cdf0e10cSrcweir 1048*cdf0e10cSrcweir return (sal_True); 1049*cdf0e10cSrcweir } 1050*cdf0e10cSrcweir 1051*cdf0e10cSrcweir pPrevious = pHandler; 1052*cdf0e10cSrcweir pHandler = pHandler->pNext; 1053*cdf0e10cSrcweir } 1054*cdf0e10cSrcweir 1055*cdf0e10cSrcweir osl_releaseMutex(SignalListMutex); 1056*cdf0e10cSrcweir 1057*cdf0e10cSrcweir return (sal_False); 1058*cdf0e10cSrcweir } 1059*cdf0e10cSrcweir 1060*cdf0e10cSrcweir /*****************************************************************************/ 1061*cdf0e10cSrcweir /* osl_raiseSignal */ 1062*cdf0e10cSrcweir /*****************************************************************************/ 1063*cdf0e10cSrcweir oslSignalAction SAL_CALL osl_raiseSignal(sal_Int32 UserSignal, void* UserData) 1064*cdf0e10cSrcweir { 1065*cdf0e10cSrcweir oslSignalInfo Info; 1066*cdf0e10cSrcweir oslSignalAction Action; 1067*cdf0e10cSrcweir 1068*cdf0e10cSrcweir if (! bInitSignal) 1069*cdf0e10cSrcweir bInitSignal = InitSignal(); 1070*cdf0e10cSrcweir 1071*cdf0e10cSrcweir osl_acquireMutex(SignalListMutex); 1072*cdf0e10cSrcweir 1073*cdf0e10cSrcweir Info.Signal = osl_Signal_User; 1074*cdf0e10cSrcweir Info.UserSignal = UserSignal; 1075*cdf0e10cSrcweir Info.UserData = UserData; 1076*cdf0e10cSrcweir 1077*cdf0e10cSrcweir Action = CallSignalHandler(&Info); 1078*cdf0e10cSrcweir 1079*cdf0e10cSrcweir osl_releaseMutex(SignalListMutex); 1080*cdf0e10cSrcweir 1081*cdf0e10cSrcweir return (Action); 1082*cdf0e10cSrcweir } 1083*cdf0e10cSrcweir 1084*cdf0e10cSrcweir /*****************************************************************************/ 1085*cdf0e10cSrcweir /* osl_setErrorReporting */ 1086*cdf0e10cSrcweir /*****************************************************************************/ 1087*cdf0e10cSrcweir sal_Bool SAL_CALL osl_setErrorReporting( sal_Bool bEnable ) 1088*cdf0e10cSrcweir { 1089*cdf0e10cSrcweir sal_Bool bOld = bErrorReportingEnabled; 1090*cdf0e10cSrcweir bErrorReportingEnabled = bEnable; 1091*cdf0e10cSrcweir 1092*cdf0e10cSrcweir return bOld; 1093*cdf0e10cSrcweir } 1094