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