|
|
|
@ -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); |
|
|
|
|