1647f063dSAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
3647f063dSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
4647f063dSAndrew Rist * or more contributor license agreements. See the NOTICE file
5647f063dSAndrew Rist * distributed with this work for additional information
6647f063dSAndrew Rist * regarding copyright ownership. The ASF licenses this file
7647f063dSAndrew Rist * to you under the Apache License, Version 2.0 (the
8647f063dSAndrew Rist * "License"); you may not use this file except in compliance
9647f063dSAndrew Rist * with the License. You may obtain a copy of the License at
10647f063dSAndrew Rist *
11647f063dSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12647f063dSAndrew Rist *
13647f063dSAndrew Rist * Unless required by applicable law or agreed to in writing,
14647f063dSAndrew Rist * software distributed under the License is distributed on an
15647f063dSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16647f063dSAndrew Rist * KIND, either express or implied. See the License for the
17647f063dSAndrew Rist * specific language governing permissions and limitations
18647f063dSAndrew Rist * under the License.
19647f063dSAndrew Rist *
20647f063dSAndrew Rist *************************************************************/
21647f063dSAndrew Rist
22647f063dSAndrew 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
13386e1cf34SPedro Giffuni { SIGPOLL, ACT_EXIT, NULL }, /* pollable event occurred */
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
getExecutableName_Impl(rtl_String ** ppstrProgName)162cdf0e10cSrcweir static void getExecutableName_Impl (rtl_String ** ppstrProgName)
163cdf0e10cSrcweir {
164*509a48ffSpfg rtl_uString * ustrProgFile = NULL;
165cdf0e10cSrcweir osl_getExecutableFile (&ustrProgFile);
166cdf0e10cSrcweir if (ustrProgFile)
167cdf0e10cSrcweir {
168*509a48ffSpfg rtl_uString * ustrProgName = NULL;
169cdf0e10cSrcweir osl_systemPathGetFileNameOrLastDirectoryPart (ustrProgFile, &ustrProgName);
170*509a48ffSpfg if (ustrProgName != NULL)
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
is_soffice_Impl(void)183cdf0e10cSrcweir static sal_Bool is_soffice_Impl (void)
184cdf0e10cSrcweir {
185cdf0e10cSrcweir sal_Int32 idx = -1;
186*509a48ffSpfg rtl_String * strProgName = NULL;
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
InitSignal()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;
208*509a48ffSpfg rtl_uString *ustrCommandArg = NULL;
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);
225*509a48ffSpfg ustrCommandArg = NULL;
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 {
25586e1cf34SPedro Giffuni /* hack: stomcatd is attaching JavaVM which 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
DeInitSignal()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
calc_md5_checksum(const char * filename,sal_uInt8 * pChecksum,sal_uInt32 nChecksumLen)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
fputs_xml(const char * string,FILE * stream)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
callback(struct dl_phdr_info * info,size_t size,void * data)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)
dynamic_section_offset(const char * name)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
ReportCrash(int Signal)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(
740910823aeSJürgen Schmidt "$OOO_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
PrintStack(int sig)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
CallSignalHandler(oslSignalInfo * pInfo)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
CallSystemHandler(int Signal)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 /*****************************************************************************/
SignalHandlerFunction(int Signal)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 /*****************************************************************************/
osl_addSignalHandler(oslSignalHandlerFunction Handler,void * pData)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 /*****************************************************************************/
osl_removeSignalHandler(oslSignalHandler Handler)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 /*****************************************************************************/
osl_raiseSignal(sal_Int32 UserSignal,void * UserData)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 /*****************************************************************************/
osl_setErrorReporting(sal_Bool bEnable)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