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