1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: signal.c,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
35 #include <osl/diagnose.h>
36 #include <osl/mutex.h>
37 #include <osl/signal.h>
42 #include <systools/win32/uwinapi.h>
44 typedef struct _oslSignalHandlerImpl
46 oslSignalHandlerFunction Handler
;
48 struct _oslSignalHandlerImpl
* pNext
;
49 } oslSignalHandlerImpl
;
51 static sal_Bool bErrorReportingEnabled
= sal_True
;
52 static sal_Bool bInitSignal
= sal_False
;
53 static oslMutex SignalListMutex
;
54 static oslSignalHandlerImpl
* SignalList
;
56 static long WINAPI
SignalHandlerFunction(LPEXCEPTION_POINTERS lpEP
);
58 static sal_Bool
InitSignal(void)
62 SignalListMutex
= osl_createMutex();
64 SetUnhandledExceptionFilter(SignalHandlerFunction
);
66 hFaultRep
= LoadLibrary( "faultrep.dll" );
70 typedef BOOL (WINAPI
*pfn_ADDEREXCLUDEDAPPLICATIONW
)(LPCWSTR
);
72 pfn_ADDEREXCLUDEDAPPLICATIONW pfn
= (pfn_ADDEREXCLUDEDAPPLICATIONW
)GetProcAddress( hFaultRep
, "AddERExcludedApplicationW" );
74 pfn( L
"SOFFICE.EXE" );
75 FreeLibrary( hFaultRep
);
81 static sal_Bool
DeInitSignal(void)
83 SetUnhandledExceptionFilter(NULL
);
85 osl_destroyMutex(SignalListMutex
);
90 static oslSignalAction
CallSignalHandler(oslSignalInfo
*pInfo
)
92 oslSignalHandlerImpl
* pHandler
= SignalList
;
93 oslSignalAction Action
= osl_Signal_ActCallNextHdl
;
95 while (pHandler
!= NULL
)
97 if ((Action
= pHandler
->Handler(pHandler
->pData
, pInfo
)) != osl_Signal_ActCallNextHdl
)
100 pHandler
= pHandler
->pNext
;
106 /*****************************************************************************/
107 /* SignalHandlerFunction */
108 /*****************************************************************************/
110 #define REPORTENV_PARAM "-crashreportenv:"
111 #define REPORTENV_PARAM2 "/crashreportenv:"
113 static BOOL
ReportCrash( LPEXCEPTION_POINTERS lpEP
)
115 BOOL fSuccess
= FALSE
;
116 BOOL fAutoReport
= FALSE
;
117 TCHAR szBuffer
[1024];
118 TCHAR szPath
[MAX_PATH
];
120 PROCESS_INFORMATION ProcessInfo
;
121 STARTUPINFO StartupInfo
;
124 if ( !bErrorReportingEnabled
)
127 /* Check if crash reporter was disabled by command line */
129 for ( argi
= 1; argi
< __argc
; argi
++ )
132 0 == stricmp( __argv
[argi
], "-nocrashreport" ) ||
133 0 == stricmp( __argv
[argi
], "/nocrashreport" )
137 0 == stricmp( __argv
[argi
], "-autocrashreport" ) ||
138 0 == stricmp( __argv
[argi
], "/autocrashreport" )
142 0 == strnicmp( __argv
[argi
], REPORTENV_PARAM
, strlen(REPORTENV_PARAM
) ) ||
143 0 == strnicmp( __argv
[argi
], REPORTENV_PARAM2
, strlen(REPORTENV_PARAM2
) )
146 const char *envparam
= __argv
[argi
] + strlen(REPORTENV_PARAM
);
147 const char *delim
= strchr(envparam
, '=' );
153 const char *variable
= envparam
;
154 size_t variable_len
= delim
- envparam
;
155 const char *value
= delim
+ 1;
156 size_t value_len
= strlen(envparam
) - variable_len
- 1;
158 if ( '\"' == *value
)
165 quote
= strchr( value
, '\"' );
167 value_len
= quote
- value
;
170 lpVariable
= _alloca( variable_len
+ 1 );
171 memcpy( lpVariable
, variable
, variable_len
);
172 lpVariable
[variable_len
] = 0;
174 lpValue
= _alloca( value_len
+ 1);
175 memcpy( lpValue
, value
, value_len
);
176 lpValue
[value_len
] = 0;
178 SetEnvironmentVariable( lpVariable
, lpValue
);
183 if ( SearchPath( NULL
, TEXT("crashrep.exe"), NULL
, MAX_PATH
, szPath
, &lpFilePart
) )
185 ZeroMemory( &StartupInfo
, sizeof(StartupInfo
) );
186 StartupInfo
.cb
= sizeof(StartupInfo
.cb
);
189 sntprintf( szBuffer
, elementsof(szBuffer
),
190 _T("%s -p %u -excp 0x%p -t %u%s"),
192 GetCurrentProcessId(),
194 GetCurrentThreadId(),
195 fAutoReport
? _T(" -noui -send") : _T(" -noui") );
205 CREATE_UNICODE_ENVIRONMENT
,
209 NULL
, NULL
, &StartupInfo
, &ProcessInfo
)
214 WaitForSingleObject( ProcessInfo
.hProcess
, INFINITE
);
215 if ( GetExitCodeProcess( ProcessInfo
.hProcess
, &dwExitCode
) && 0 == dwExitCode
)
225 /*****************************************************************************/
226 /* SignalHandlerFunction */
227 /*****************************************************************************/
229 static BOOL WINAPI
IsWin95A(void)
233 ZeroMemory( &ovi
, sizeof(ovi
) );
234 ovi
.dwOSVersionInfoSize
= sizeof(ovi
);
236 if ( GetVersionEx( &ovi
) )
237 /* See MSDN January 2000 documentation of GetVersionEx */
238 return (ovi
.dwPlatformId
== VER_PLATFORM_WIN32_WINDOWS
) &&
239 (ovi
.dwMajorVersion
<= 4) &&
240 (ovi
.dwMinorVersion
== 0) &&
241 (ovi
.dwBuildNumber
== 0x040003B6);
243 /* Something wrent wrong. So assume we have an older operating prior Win95 */
248 /* magic Microsoft C++ compiler exception constant */
249 #define EXCEPTION_MSC_CPP_EXCEPTION 0xe06d7363
251 static long WINAPI
SignalHandlerFunction(LPEXCEPTION_POINTERS lpEP
)
253 static sal_Bool bNested
= sal_False
;
254 sal_Bool bRaiseCrashReporter
= sal_False
;
256 oslSignalAction Action
;
258 Info
.UserSignal
= lpEP
->ExceptionRecord
->ExceptionCode
;
259 Info
.UserData
= NULL
;
261 switch (lpEP
->ExceptionRecord
->ExceptionCode
)
263 /* Transform unhandled exceptions into access violations.
264 Microsoft C++ compiler (add more for other compilers if necessary).
266 case EXCEPTION_MSC_CPP_EXCEPTION
:
267 case EXCEPTION_ACCESS_VIOLATION
:
268 Info
.Signal
= osl_Signal_AccessViolation
;
269 bRaiseCrashReporter
= sal_True
;
272 case EXCEPTION_INT_DIVIDE_BY_ZERO
:
273 Info
.Signal
= osl_Signal_IntegerDivideByZero
;
274 bRaiseCrashReporter
= sal_True
;
277 case EXCEPTION_FLT_DIVIDE_BY_ZERO
:
278 Info
.Signal
= osl_Signal_FloatDivideByZero
;
279 bRaiseCrashReporter
= sal_True
;
282 case EXCEPTION_BREAKPOINT
:
283 Info
.Signal
= osl_Signal_DebugBreak
;
287 Info
.Signal
= osl_Signal_System
;
288 bRaiseCrashReporter
= sal_True
;
296 if ( bRaiseCrashReporter
&& ReportCrash( lpEP
) || IsWin95A() )
298 CallSignalHandler(&Info
);
299 Action
= osl_Signal_ActKillApp
;
302 Action
= CallSignalHandler(&Info
);
305 Action
= osl_Signal_ActKillApp
;
310 case osl_Signal_ActCallNextHdl
:
311 return (EXCEPTION_CONTINUE_SEARCH
);
313 case osl_Signal_ActAbortApp
:
314 return (EXCEPTION_EXECUTE_HANDLER
);
316 case osl_Signal_ActKillApp
:
317 SetErrorMode(SEM_NOGPFAULTERRORBOX
);
322 return (EXCEPTION_CONTINUE_EXECUTION
);
325 /*****************************************************************************/
326 /* osl_addSignalHandler */
327 /*****************************************************************************/
328 oslSignalHandler SAL_CALL
osl_addSignalHandler(oslSignalHandlerFunction Handler
, void* pData
)
330 oslSignalHandlerImpl
* pHandler
;
332 OSL_ASSERT(Handler
!= NULL
);
335 bInitSignal
= InitSignal();
337 pHandler
= calloc(1, sizeof(oslSignalHandlerImpl
));
339 if (pHandler
!= NULL
)
341 pHandler
->Handler
= Handler
;
342 pHandler
->pData
= pData
;
344 osl_acquireMutex(SignalListMutex
);
346 pHandler
->pNext
= SignalList
;
347 SignalList
= pHandler
;
349 osl_releaseMutex(SignalListMutex
);
357 /*****************************************************************************/
358 /* osl_removeSignalHandler */
359 /*****************************************************************************/
360 sal_Bool SAL_CALL
osl_removeSignalHandler(oslSignalHandler Handler
)
362 oslSignalHandlerImpl
*pHandler
, *pPrevious
= NULL
;
364 OSL_ASSERT(Handler
!= NULL
);
367 bInitSignal
= InitSignal();
369 osl_acquireMutex(SignalListMutex
);
371 pHandler
= SignalList
;
373 while (pHandler
!= NULL
)
375 if (pHandler
== Handler
)
378 pPrevious
->pNext
= pHandler
->pNext
;
380 SignalList
= pHandler
->pNext
;
382 osl_releaseMutex(SignalListMutex
);
384 if (SignalList
== NULL
)
385 bInitSignal
= DeInitSignal();
392 pPrevious
= pHandler
;
393 pHandler
= pHandler
->pNext
;
396 osl_releaseMutex(SignalListMutex
);
401 /*****************************************************************************/
402 /* osl_raiseSignal */
403 /*****************************************************************************/
404 oslSignalAction SAL_CALL
osl_raiseSignal(sal_Int32 UserSignal
, void* UserData
)
407 oslSignalAction Action
;
410 bInitSignal
= InitSignal();
412 osl_acquireMutex(SignalListMutex
);
414 Info
.Signal
= osl_Signal_User
;
415 Info
.UserSignal
= UserSignal
;
416 Info
.UserData
= UserData
;
418 Action
= CallSignalHandler(&Info
);
420 osl_releaseMutex(SignalListMutex
);
425 /*****************************************************************************/
426 /* osl_setErrorReporting */
427 /*****************************************************************************/
428 sal_Bool SAL_CALL
osl_setErrorReporting( sal_Bool bEnable
)
430 sal_Bool bOld
= bErrorReportingEnabled
;
431 bErrorReportingEnabled
= bEnable
;