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