xref: /trunk/main/sal/osl/unx/signal.c (revision 534d93521fb9d960038706348aeef53f37423a94)
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( "&amp;", stream );
388cdf0e10cSrcweir             break;
389cdf0e10cSrcweir         case '<':
390cdf0e10cSrcweir             result = fputs( "&lt;", stream );
391cdf0e10cSrcweir             break;
392cdf0e10cSrcweir         case '>':
393cdf0e10cSrcweir             result = fputs( "&gt;", 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