Browse Source

crash dump support for windows

git-svn-id: svn://svn.lighttpd.net/xcache/trunk@914 c26eb9a1-5813-0410-bd6c-c2e55f420ca7
3.0
Xuefer 9 years ago
parent
commit
8f07263463
  1. 111
      xcache.c

111
xcache.c

@ -3335,6 +3335,106 @@ static zend_function_entry xcache_functions[] = /* {{{ */
};
/* }}} */
#ifdef ZEND_WIN32
#include "dbghelp.h"
typedef BOOL (WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD dwPid, HANDLE hFile, MINIDUMP_TYPE DumpType,
CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam
);
static PTOP_LEVEL_EXCEPTION_FILTER oldFilter;
static HMODULE dbghelpModule = NULL;
static char crash_dumpPath[_MAX_PATH];
static MINIDUMPWRITEDUMP dbghelp_MiniDumpWriteDump;
static LONG WINAPI miniDumperFilter(struct _EXCEPTION_POINTERS *pExceptionInfo) /* {{{ */
{
HANDLE fileHandle;
SetUnhandledExceptionFilter(oldFilter);
/* create the file */
fileHandle = CreateFile(crash_dumpPath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (fileHandle != INVALID_HANDLE_VALUE) {
MINIDUMP_EXCEPTION_INFORMATION exceptionInformation;
BOOL ok;
exceptionInformation.ThreadId = GetCurrentThreadId();
exceptionInformation.ExceptionPointers = pExceptionInfo;
exceptionInformation.ClientPointers = FALSE;
/* write the dump */
ok = dbghelp_MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), fileHandle, MiniDumpNormal, &exceptionInformation, NULL, NULL);
CloseHandle(fileHandle);
if (ok) {
zend_error(E_ERROR, "Saved dump file to '%s'", crash_dumpPath);
return EXCEPTION_EXECUTE_HANDLER;
}
else {
zend_error(E_ERROR, "Failed to save dump file to '%s' (error %d)", crash_dumpPath, GetLastError());
}
}
else {
zend_error(E_ERROR, "Failed to create dump file '%s' (error %d)", crash_dumpPath, GetLastError());
}
return EXCEPTION_CONTINUE_SEARCH;
}
/* }}} */
static void xcache_restore_crash_handler() /* {{{ */
{
if (oldFilter) {
SetUnhandledExceptionFilter(oldFilter);
oldFilter = NULL;
}
}
/* }}} */
static void xcache_init_crash_handler() /* {{{ */
{
/* firstly see if dbghelp.dll is around and has the function we need
look next to the EXE first, as the one in System32 might be old
(e.g. Windows 2000) */
char dbghelpPath[_MAX_PATH];
if (GetModuleFileName(NULL, dbghelpPath, _MAX_PATH)) {
char *slash = strchr(dbghelpPath, '\\');
if (slash) {
strcpy(slash + 1, "DBGHELP.DLL");
dbghelpModule = LoadLibrary(dbghelpPath);
}
}
if (!dbghelpModule) {
/* load any version we can */
dbghelpModule = LoadLibrary("DBGHELP.DLL");
if (!dbghelpModule) {
zend_error(E_ERROR, "Unable to enable crash dump saver: %s", "DBGHELP.DLL not found");
return;
}
}
dbghelp_MiniDumpWriteDump = (MINIDUMPWRITEDUMP)GetProcAddress(dbghelpModule, "MiniDumpWriteDump");
if (dbghelp_MiniDumpWriteDump) {
zend_error(E_ERROR, "Unable to enable crash dump saver: %s", "DBGHELP.DLL too old");
return;
}
/* work out a good place for the dump file */
{
char tmpPath[_MAX_PATH];
if (!GetTempPath(_MAX_PATH, tmpPath)) {
strcpy(tmpPath, "c:\\temp");
}
sprintf(crash_dumpPath, "%s\\php-%s-xcache-%s-%lu.dmp", PHP_VERSION, XCACHE_VERSION, (unsigned long) GetCurrentProcessId());
}
oldFilter = SetUnhandledExceptionFilter(&miniDumperFilter);
}
/* }}} */
#else
/* old signal handlers {{{ */
typedef void (*xc_sighandler_t)(int);
#define FOREACH_SIG(sig) static xc_sighandler_t old_##sig##_handler = NULL
@ -3342,7 +3442,7 @@ typedef void (*xc_sighandler_t)(int);
#undef FOREACH_SIG
/* }}} */
static void xcache_signal_handler(int sig);
static void xcache_restore_signal_handler() /* {{{ */
static void xcache_restore_crash_handler() /* {{{ */
{
#define FOREACH_SIG(sig) do { \
if (old_##sig##_handler != xcache_signal_handler) { \
@ -3356,7 +3456,7 @@ static void xcache_restore_signal_handler() /* {{{ */
#undef FOREACH_SIG
}
/* }}} */
static void xcache_init_signal_handler() /* {{{ */
static void xcache_init_crash_handler() /* {{{ */
{
#define FOREACH_SIG(sig) \
old_##sig##_handler = signal(sig, xcache_signal_handler)
@ -3366,7 +3466,7 @@ static void xcache_init_signal_handler() /* {{{ */
/* }}} */
static void xcache_signal_handler(int sig) /* {{{ */
{
xcache_restore_signal_handler();
xcache_restore_crash_handler();
if (xc_coredump_dir && xc_coredump_dir[0]) {
if (chdir(xc_coredump_dir) != 0) {
/* error, but nothing can do about it
@ -3376,6 +3476,7 @@ static void xcache_signal_handler(int sig) /* {{{ */
raise(sig);
}
/* }}} */
#endif
/* {{{ PHP_INI */
@ -3711,7 +3812,7 @@ static PHP_MINIT_FUNCTION(xcache)
}
if (xc_coredump_dir && xc_coredump_dir[0]) {
xcache_init_signal_handler();
xcache_init_crash_handler();
}
xc_init_constant(module_number TSRMLS_CC);
@ -3766,7 +3867,7 @@ static PHP_MSHUTDOWN_FUNCTION(xcache)
xc_util_destroy();
if (xc_coredump_dir && xc_coredump_dir[0]) {
xcache_restore_signal_handler();
xcache_restore_crash_handler();
}
if (xc_coredump_dir) {
pefree(xc_coredump_dir, 1);

Loading…
Cancel
Save