Bump for 3.6-28
[LibreOffice.git] / sal / osl / w32 / signal.cxx
blob73d7f5e27d398e03491074a368dd4bba43fead01
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 /* system headers */
30 #include "system.h"
31 #include <tchar.h>
33 #include "file_url.h"
34 #include "path_helper.hxx"
36 #include <osl/diagnose.h>
37 #include <osl/mutex.h>
38 #include <osl/signal.h>
39 #ifndef __MINGW32__
40 #include <DbgHelp.h>
41 #endif
42 #include <errorrep.h>
43 #include <systools/win32/uwinapi.h>
44 #include <sal/macros.h>
46 typedef struct _oslSignalHandlerImpl
48 oslSignalHandlerFunction Handler;
49 void* pData;
50 struct _oslSignalHandlerImpl* pNext;
51 } oslSignalHandlerImpl;
53 static sal_Bool bErrorReportingEnabled = sal_True;
54 static sal_Bool bInitSignal = sal_False;
55 static oslMutex SignalListMutex;
56 static oslSignalHandlerImpl* SignalList;
58 static long WINAPI SignalHandlerFunction(LPEXCEPTION_POINTERS lpEP);
60 static sal_Bool InitSignal(void)
62 HMODULE hFaultRep;
64 SignalListMutex = osl_createMutex();
66 SetUnhandledExceptionFilter(SignalHandlerFunction);
68 hFaultRep = LoadLibrary( "faultrep.dll" );
69 if ( hFaultRep )
71 pfn_ADDEREXCLUDEDAPPLICATIONW pfn = (pfn_ADDEREXCLUDEDAPPLICATIONW)GetProcAddress( hFaultRep, "AddERExcludedApplicationW" );
72 if ( pfn )
73 pfn( L"SOFFICE.EXE" );
74 FreeLibrary( hFaultRep );
77 return sal_True;
80 static sal_Bool DeInitSignal(void)
82 SetUnhandledExceptionFilter(NULL);
84 osl_destroyMutex(SignalListMutex);
86 return sal_False;
89 static oslSignalAction CallSignalHandler(oslSignalInfo *pInfo)
91 oslSignalHandlerImpl* pHandler = SignalList;
92 oslSignalAction Action = osl_Signal_ActCallNextHdl;
94 while (pHandler != NULL)
96 if ((Action = pHandler->Handler(pHandler->pData, pInfo)) != osl_Signal_ActCallNextHdl)
97 break;
99 pHandler = pHandler->pNext;
102 return Action;
105 /*****************************************************************************/
106 /* SignalHandlerFunction */
107 /*****************************************************************************/
109 #define REPORTENV_PARAM "-crashreportenv:"
110 #define REPORTENV_PARAM2 "/crashreportenv:"
112 static BOOL ReportCrash( LPEXCEPTION_POINTERS lpEP )
114 BOOL fSuccess = FALSE;
115 BOOL fAutoReport = FALSE;
116 TCHAR szBuffer[1024];
117 ::osl::LongPathBuffer< sal_Char > aPath( MAX_LONG_PATH );
118 LPTSTR lpFilePart;
119 PROCESS_INFORMATION ProcessInfo;
120 STARTUPINFO StartupInfo;
121 int argi;
123 if ( !bErrorReportingEnabled )
124 return FALSE;
126 /* Check if crash reporter was disabled by command line */
128 for ( argi = 1; argi < __argc; argi++ )
130 if (
131 0 == stricmp( __argv[argi], "--nocrashreport" ) ||
132 0 == stricmp( __argv[argi], "/nocrashreport" )
134 return FALSE;
135 else if (
136 0 == stricmp( __argv[argi], "--autocrashreport" ) ||
137 0 == stricmp( __argv[argi], "/autocrashreport" )
139 fAutoReport = TRUE;
140 else if (
141 0 == strnicmp( __argv[argi], REPORTENV_PARAM, strlen(REPORTENV_PARAM) ) ||
142 0 == strnicmp( __argv[argi], REPORTENV_PARAM2, strlen(REPORTENV_PARAM2) )
145 const char *envparam = __argv[argi] + strlen(REPORTENV_PARAM);
146 const char *delim = strchr(envparam, '=' );
148 if ( delim )
150 CHAR *lpVariable;
151 CHAR *lpValue;
152 const char *variable = envparam;
153 size_t variable_len = delim - envparam;
154 const char *value = delim + 1;
155 size_t value_len = strlen(envparam) - variable_len - 1;
157 if ( '\"' == *value )
159 const char *quote;
161 value++;
162 value_len--;
164 quote = strchr( value, '\"' );
165 if ( quote )
166 value_len = quote - value;
169 lpVariable = reinterpret_cast< CHAR* >( _alloca( variable_len + 1 ) );
170 memcpy( lpVariable, variable, variable_len );
171 lpVariable[variable_len] = 0;
173 lpValue = reinterpret_cast< CHAR* >( _alloca( value_len + 1) );
174 memcpy( lpValue, value, value_len );
175 lpValue[value_len] = 0;
177 SetEnvironmentVariable( lpVariable, lpValue );
182 if ( SearchPath( NULL, TEXT( "crashrep.exe" ), NULL, aPath.getBufSizeInSymbols(), aPath, &lpFilePart ) )
184 ZeroMemory( &StartupInfo, sizeof(StartupInfo) );
185 StartupInfo.cb = sizeof(StartupInfo.cb);
188 sntprintf( szBuffer, SAL_N_ELEMENTS(szBuffer),
189 _T("%s -p %lu -excp 0x%p -t %lu%s"),
190 static_cast<sal_Char*>( aPath ),
191 GetCurrentProcessId(),
192 lpEP,
193 GetCurrentThreadId(),
194 fAutoReport ? _T(" -noui -send") : _T(" -noui") );
196 if (
197 CreateProcess(
198 NULL,
199 szBuffer,
200 NULL,
201 NULL,
202 FALSE,
203 #ifdef UNICODE
204 CREATE_UNICODE_ENVIRONMENT,
205 #else
207 #endif
208 NULL, NULL, &StartupInfo, &ProcessInfo )
211 DWORD dwExitCode;
213 WaitForSingleObject( ProcessInfo.hProcess, INFINITE );
214 if ( GetExitCodeProcess( ProcessInfo.hProcess, &dwExitCode ) && 0 == dwExitCode )
216 fSuccess = TRUE;
221 return fSuccess;
224 /*****************************************************************************/
225 /* SignalHandlerFunction */
226 /*****************************************************************************/
228 /* magic Microsoft C++ compiler exception constant */
229 #define EXCEPTION_MSC_CPP_EXCEPTION 0xe06d7363
231 static long WINAPI SignalHandlerFunction(LPEXCEPTION_POINTERS lpEP)
233 static sal_Bool bNested = sal_False;
234 sal_Bool bRaiseCrashReporter = sal_False;
235 oslSignalInfo Info;
236 oslSignalAction Action;
238 Info.UserSignal = lpEP->ExceptionRecord->ExceptionCode;
239 Info.UserData = NULL;
241 switch (lpEP->ExceptionRecord->ExceptionCode)
243 /* Transform unhandled exceptions into access violations.
244 Microsoft C++ compiler (add more for other compilers if necessary).
246 case EXCEPTION_MSC_CPP_EXCEPTION:
247 case EXCEPTION_ACCESS_VIOLATION:
248 Info.Signal = osl_Signal_AccessViolation;
249 bRaiseCrashReporter = sal_True;
250 break;
252 case EXCEPTION_INT_DIVIDE_BY_ZERO:
253 Info.Signal = osl_Signal_IntegerDivideByZero;
254 bRaiseCrashReporter = sal_True;
255 break;
257 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
258 Info.Signal = osl_Signal_FloatDivideByZero;
259 bRaiseCrashReporter = sal_True;
260 break;
262 case EXCEPTION_BREAKPOINT:
263 Info.Signal = osl_Signal_DebugBreak;
264 break;
266 default:
267 Info.Signal = osl_Signal_System;
268 bRaiseCrashReporter = sal_True;
269 break;
272 if ( !bNested )
274 bNested = sal_True;
276 if ( bRaiseCrashReporter && ReportCrash( lpEP ) )
278 CallSignalHandler(&Info);
279 Action = osl_Signal_ActKillApp;
281 else
282 Action = CallSignalHandler(&Info);
284 else
285 Action = osl_Signal_ActKillApp;
288 switch ( Action )
290 case osl_Signal_ActCallNextHdl:
291 return (EXCEPTION_CONTINUE_SEARCH);
293 case osl_Signal_ActAbortApp:
294 return (EXCEPTION_EXECUTE_HANDLER);
296 case osl_Signal_ActKillApp:
297 SetErrorMode(SEM_NOGPFAULTERRORBOX);
298 exit(255);
299 break;
300 default:
301 break;
304 return (EXCEPTION_CONTINUE_EXECUTION);
307 /*****************************************************************************/
308 /* osl_addSignalHandler */
309 /*****************************************************************************/
310 oslSignalHandler SAL_CALL osl_addSignalHandler(oslSignalHandlerFunction Handler, void* pData)
312 oslSignalHandlerImpl* pHandler;
314 OSL_ASSERT(Handler != NULL);
316 if (! bInitSignal)
317 bInitSignal = InitSignal();
319 pHandler = reinterpret_cast< oslSignalHandlerImpl* >( calloc( 1, sizeof(oslSignalHandlerImpl) ) );
321 if (pHandler != NULL)
323 pHandler->Handler = Handler;
324 pHandler->pData = pData;
326 osl_acquireMutex(SignalListMutex);
328 pHandler->pNext = SignalList;
329 SignalList = pHandler;
331 osl_releaseMutex(SignalListMutex);
333 return (pHandler);
336 return (NULL);
339 /*****************************************************************************/
340 /* osl_removeSignalHandler */
341 /*****************************************************************************/
342 sal_Bool SAL_CALL osl_removeSignalHandler(oslSignalHandler Handler)
344 oslSignalHandlerImpl *pHandler, *pPrevious = NULL;
346 OSL_ASSERT(Handler != NULL);
348 if (! bInitSignal)
349 bInitSignal = InitSignal();
351 osl_acquireMutex(SignalListMutex);
353 pHandler = SignalList;
355 while (pHandler != NULL)
357 if (pHandler == Handler)
359 if (pPrevious)
360 pPrevious->pNext = pHandler->pNext;
361 else
362 SignalList = pHandler->pNext;
364 osl_releaseMutex(SignalListMutex);
366 if (SignalList == NULL)
367 bInitSignal = DeInitSignal();
369 free(pHandler);
371 return (sal_True);
374 pPrevious = pHandler;
375 pHandler = pHandler->pNext;
378 osl_releaseMutex(SignalListMutex);
380 return (sal_False);
383 /*****************************************************************************/
384 /* osl_raiseSignal */
385 /*****************************************************************************/
386 oslSignalAction SAL_CALL osl_raiseSignal(sal_Int32 UserSignal, void* UserData)
388 oslSignalInfo Info;
389 oslSignalAction Action;
391 if (! bInitSignal)
392 bInitSignal = InitSignal();
394 osl_acquireMutex(SignalListMutex);
396 Info.Signal = osl_Signal_User;
397 Info.UserSignal = UserSignal;
398 Info.UserData = UserData;
400 Action = CallSignalHandler(&Info);
402 osl_releaseMutex(SignalListMutex);
404 return (Action);
407 /*****************************************************************************/
408 /* osl_setErrorReporting */
409 /*****************************************************************************/
410 sal_Bool SAL_CALL osl_setErrorReporting( sal_Bool bEnable )
412 sal_Bool bOld = bErrorReportingEnabled;
413 bErrorReportingEnabled = bEnable;
415 return bOld;
418 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */