| | 3338 | #ifdef ZEND_WIN32 |
| | 3339 | #include "dbghelp.h" |
| | 3340 | typedef BOOL (WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD dwPid, HANDLE hFile, MINIDUMP_TYPE DumpType, |
| | 3341 | CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, |
| | 3342 | CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, |
| | 3343 | CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam |
| | 3344 | ); |
| | 3345 | |
| | 3346 | static PTOP_LEVEL_EXCEPTION_FILTER oldFilter; |
| | 3347 | static HMODULE dbghelpModule = NULL; |
| | 3348 | static char crash_dumpPath[_MAX_PATH]; |
| | 3349 | static MINIDUMPWRITEDUMP dbghelp_MiniDumpWriteDump; |
| | 3350 | |
| | 3351 | static LONG WINAPI miniDumperFilter(struct _EXCEPTION_POINTERS *pExceptionInfo) /* {{{ */ |
| | 3352 | { |
| | 3353 | HANDLE fileHandle; |
| | 3354 | |
| | 3355 | SetUnhandledExceptionFilter(oldFilter); |
| | 3356 | |
| | 3357 | /* create the file */ |
| | 3358 | fileHandle = CreateFile(crash_dumpPath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); |
| | 3359 | |
| | 3360 | if (fileHandle != INVALID_HANDLE_VALUE) { |
| | 3361 | MINIDUMP_EXCEPTION_INFORMATION exceptionInformation; |
| | 3362 | BOOL ok; |
| | 3363 | |
| | 3364 | exceptionInformation.ThreadId = GetCurrentThreadId(); |
| | 3365 | exceptionInformation.ExceptionPointers = pExceptionInfo; |
| | 3366 | exceptionInformation.ClientPointers = FALSE; |
| | 3367 | |
| | 3368 | /* write the dump */ |
| | 3369 | ok = dbghelp_MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), fileHandle, MiniDumpNormal, &exceptionInformation, NULL, NULL); |
| | 3370 | CloseHandle(fileHandle); |
| | 3371 | if (ok) { |
| | 3372 | zend_error(E_ERROR, "Saved dump file to '%s'", crash_dumpPath); |
| | 3373 | return EXCEPTION_EXECUTE_HANDLER; |
| | 3374 | } |
| | 3375 | else { |
| | 3376 | zend_error(E_ERROR, "Failed to save dump file to '%s' (error %d)", crash_dumpPath, GetLastError()); |
| | 3377 | } |
| | 3378 | } |
| | 3379 | else { |
| | 3380 | zend_error(E_ERROR, "Failed to create dump file '%s' (error %d)", crash_dumpPath, GetLastError()); |
| | 3381 | } |
| | 3382 | |
| | 3383 | return EXCEPTION_CONTINUE_SEARCH; |
| | 3384 | } |
| | 3385 | /* }}} */ |
| | 3386 | |
| | 3387 | static void xcache_restore_crash_handler() /* {{{ */ |
| | 3388 | { |
| | 3389 | if (oldFilter) { |
| | 3390 | SetUnhandledExceptionFilter(oldFilter); |
| | 3391 | oldFilter = NULL; |
| | 3392 | } |
| | 3393 | } |
| | 3394 | /* }}} */ |
| | 3395 | static void xcache_init_crash_handler() /* {{{ */ |
| | 3396 | { |
| | 3397 | /* firstly see if dbghelp.dll is around and has the function we need |
| | 3398 | look next to the EXE first, as the one in System32 might be old |
| | 3399 | (e.g. Windows 2000) */ |
| | 3400 | char dbghelpPath[_MAX_PATH]; |
| | 3401 | |
| | 3402 | if (GetModuleFileName(NULL, dbghelpPath, _MAX_PATH)) { |
| | 3403 | char *slash = strchr(dbghelpPath, '\\'); |
| | 3404 | if (slash) { |
| | 3405 | strcpy(slash + 1, "DBGHELP.DLL"); |
| | 3406 | dbghelpModule = LoadLibrary(dbghelpPath); |
| | 3407 | } |
| | 3408 | } |
| | 3409 | |
| | 3410 | if (!dbghelpModule) { |
| | 3411 | /* load any version we can */ |
| | 3412 | dbghelpModule = LoadLibrary("DBGHELP.DLL"); |
| | 3413 | if (!dbghelpModule) { |
| | 3414 | zend_error(E_ERROR, "Unable to enable crash dump saver: %s", "DBGHELP.DLL not found"); |
| | 3415 | return; |
| | 3416 | } |
| | 3417 | } |
| | 3418 | |
| | 3419 | dbghelp_MiniDumpWriteDump = (MINIDUMPWRITEDUMP)GetProcAddress(dbghelpModule, "MiniDumpWriteDump"); |
| | 3420 | if (dbghelp_MiniDumpWriteDump) { |
| | 3421 | zend_error(E_ERROR, "Unable to enable crash dump saver: %s", "DBGHELP.DLL too old"); |
| | 3422 | return; |
| | 3423 | } |
| | 3424 | |
| | 3425 | /* work out a good place for the dump file */ |
| | 3426 | { |
| | 3427 | char tmpPath[_MAX_PATH]; |
| | 3428 | if (!GetTempPath(_MAX_PATH, tmpPath)) { |
| | 3429 | strcpy(tmpPath, "c:\\temp"); |
| | 3430 | } |
| | 3431 | sprintf(crash_dumpPath, "%s\\php-%s-xcache-%s-%lu.dmp", PHP_VERSION, XCACHE_VERSION, (unsigned long) GetCurrentProcessId()); |
| | 3432 | } |
| | 3433 | |
| | 3434 | oldFilter = SetUnhandledExceptionFilter(&miniDumperFilter); |
| | 3435 | } |
| | 3436 | /* }}} */ |
| | 3437 | #else |