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