From: Date: February 18 2008 10:51am Subject: bk commit into 5.0 tree (vvaintroub:1.2568) BUG#31745 List-Archive: http://lists.mysql.com/commits/42471 X-Bug: 31745 Message-Id: <200802180952.m1I9q6lB011354@mail.mysql.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: quoted-printable Below is the list of changes that have just been committed into a local= =0A5.0 repository of vvaintroub. When vvaintroub does a push these changes= =0Awill be propagated to the main repository and, within 24 hours after= the=0Apush, to the public repository.=0AFor information on how to access= the public repository=0Asee http://dev.mysql.com/doc/mysql/en/installing-source-tree.html= =0A=0AChangeSet@stripped, 2008-02-18 10:51:24+01:00, vvaintroub@wva. +5 -0= =0A Bug#31745 - crash handler does not work on Windows=0A - Replace per-thread= signal()'s with SetUnhandledExceptionFilter(). =0A The only remaining= signal() is for SIGABRT (default abort()=0A handler in VS2005 is broken,= i.e removes user exception filter)=0A - remove MessageBox()'es from error= handling code=0A - Windows port for print_stacktrace() and write_core()= =0A=0A sql/CMakeLists.txt@stripped, 2008-02-18 10:51:21+01:00, vvaintroub@wva.= +1 -1=0A Implement stack tracing on and generating crash dumps on Windows= =0A=0A sql/mysqld.cc@stripped, 2008-02-18 10:51:21+01:00, vvaintroub@wva.= +169 -46=0A Correct signal handling on Windows. =0A - For console= events, like CTRL-C use SetConsoleCtrlHandler=0A - For exceptions like= access violation, use SetUnhandledExceptionFilter=0A - For SIGABRT generate= exception via __debugbreak() intrinsic=0A if built with VS2005 and= later , since default SIGABRT handler =0A replaces unhandled exception= filter specified by user=0A - make provisions to debug exception filter,= as it is not trivial =0A (should be compiled with /DDEBUG_UNHANDLED_EXCEPTION_FILTER)= =0A =0A =0A=0A sql/sql_parse.cc@stripped, 2008-02-18 10:51:22+01:00,= vvaintroub@wva. +2 -17=0A Remove message box from windows signal handler.= =0A The only thread specific handler left is for SIGABRT,=0A which= is broken on VS2005 and later (user specified unhandled exception =0A = filter gets overwritten)=0A=0A sql/stacktrace.c@stripped, 2008-02-18 10:51:22+01:00,= vvaintroub@wva. +258 -5=0A Stack tracing and generating crash dumps= on Windows=0A=0A sql/stacktrace.h@stripped, 2008-02-18 10:51:23+01:00, vvaintroub@wva.= +18 -5=0A Implement print_stacktrace and write_core on Windows=0A=0Adiff= -Nrup a/sql/CMakeLists.txt b/sql/CMakeLists.txt=0A--- a/sql/CMakeLists.txt= 2007-08-29 22:28:33 +02:00=0A+++ b/sql/CMakeLists.txt 2008-02-18 10:51:21= +01:00=0A@@ -48,7 +48,7 @@ ENDIF(DISABLE_GRANT_OPTIONS)=0A =0A ADD_EXECUTABLE(mysqld${MYSQLD_EXE_SUFFIX}= =0A ../sql-common/client.c derror.cc des_key_file.cc=0A- = discover.cc ../libmysql/errmsg.c field.cc field_conv.cc =0A+ = discover.cc ../libmysql/errmsg.c field.cc stacktrace.c stacktrace.h= field_conv.cc =0A filesort.cc gstream.cc ha_blackhole.cc= =0A ha_archive.cc ha_heap.cc ha_myisam.cc ha_myisammrg.cc= =0A ha_innodb.cc ha_federated.cc ha_berkeley.cc=0Adiff -Nrup= a/sql/mysqld.cc b/sql/mysqld.cc=0A--- a/sql/mysqld.cc 2007-12-14 06:53:52= +01:00=0A+++ b/sql/mysqld.cc 2008-02-18 10:51:21 +01:00=0A@@ -138,6 +138,13= @@ extern "C" { // Because of SCO 3.2V4=0A #include =0A= #endif=0A =0A+#ifdef __WIN__ =0A+#include =0A+#define SIGNAL_FMT= "exception 0x%x"=0A+#else=0A+#define SIGNAL_FMT "signal %d"=0A+#endif=0A+= =0A #ifdef __NETWARE__=0A #define zVOLSTATE_ACTIVE 6=0A #define zVOLSTATE_DEACTIVE= 2=0A@@ -227,6 +234,7 @@ inline void set_proper_floating_point_mo=0A extern= "C" int gethostname(char *name, int namelen);=0A #endif=0A =0A+extern "C"= sig_handler handle_segfault(int sig);=0A =0A /* Constants */=0A =0A@@ -1031,9= +1039,6 @@ static void __cdecl kill_server(int sig_=0A #endif=0A close_connections();= =0A if (sig !=3D MYSQL_KILL_SIGNAL &&=0A-#ifdef __WIN__=0A- sig !=3D= SIGINT && /* Bug#18235 */=0A-#endif=0A sig !=3D 0)=0A unireg_abort(1);= /* purecov: inspected */=0A else=0A@@ -1592,8 +1597,7 @@ static void= network_init(void)=0A FORMAT_MESSAGE_FROM_SYSTEM,=0A NULL,= error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),=0A (LPTSTR) &lpMsgBuf,= 0, NULL );=0A- MessageBox(NULL, (LPTSTR) lpMsgBuf, "Error from CreateNamedPipe",= =0A- MB_OK|MB_ICONINFORMATION);=0A+ sql_perror((char *)lpMsgBuf);=0A= LocalFree(lpMsgBuf);=0A unireg_abort(1);=0A }=0A@@ -1796,19 +1800,157= @@ extern "C" sig_handler abort_thread(int =0A ******************************************************************************/= =0A =0A =0A-#if defined(__WIN__) || defined(OS2)=0A-static void init_signals(void)= =0A-{=0A- int signals[] =3D {SIGINT,SIGILL,SIGFPE,SIGSEGV,SIGTERM,SIGABRT= } ;=0A- for (uint i=3D0 ; i < sizeof(signals)/sizeof(int) ; i++)=0A- = signal(signals[i], kill_server) ;=0A #if defined(__WIN__)=0A- signal(SIGBREAK,SIG_IGN);= //ignore SIGBREAK for NT=0A-#else=0A- signal(SIGBREAK, kill_server);=0A+= =0A+=0A+/*=0A+ On Windows, we use native SetConsoleCtrlHandler for handle= events like Ctrl-C=0A+ with graceful shutdown.=0A+ Also, we do not use= signal(), but SetUnhandledExceptionFilter instead - as it=0A+ provides= possibility to pass the exception to just-in-time debugger, collect=0A+= dumps and potentially also the exception and thread context used to output= =0A+ callstack.=0A+*/=0A+=0A+static BOOL WINAPI console_event_handler(= DWORD type ) =0A+{=0A+ DBUG_ENTER("console_event_handler");=0A+ if(type= =3D=3D CTRL_C_EVENT)=0A+ {=0A+ kill_server(MYSQL_KILL_SIGNAL);=0A+= DBUG_RETURN(TRUE);=0A+ }=0A+ DBUG_RETURN(FALSE);=0A+}=0A+=0A+=0A+/*= =0A+ In Visual Studio 2005 and later, default SIGABRT handler will overwrite= =0A+ any unhandled exception filter set by the application and will try= to=0A+ call JIT debugger. This is not what we want, this we calling __debugbreak= =0A+ to stop in debugger, if process is being debugged or to generate = =0A+ EXCEPTION_BREAKPOINT and then handle_segfault will do its magic.=0A+*/= =0A+=0A+#if (_MSC_VER >=3D 1400)=0A+static void my_sigabrt_handler(int sig)= =0A+{=0A+ __debugbreak();=0A+}=0A #endif=0A+=0A+void win_install_sigabrt_handler(void)= =0A+{=0A+#if (_MSC_VER >=3D1400)=0A+ /*abort() should not override our= exception filter*/=0A+ _set_abort_behavior(0,_CALL_REPORTFAULT);=0A+ = signal(SIGABRT,my_sigabrt_handler);=0A+#endif=0A+}=0A+=0A+#ifdef DEBUG_UNHANDLED_EXCEPTION_FILTER= =0A+#define DEBUGGER_ATTACH_TIMEOUT 120=0A+/*=0A+ Wait for debugger to= attach and break into debugger. If debugger is not attached,=0A+ resume= after timeout.=0A+*/=0A+static void wait_for_debugger(int timeout_sec)= =0A+{=0A+ if(!IsDebuggerPresent())=0A+ {=0A+ int i;=0A+ printf("Waiting= for debugger to attach, pid=3D%u\n",GetCurrentProcessId());=0A+ fflush(stdout);= =0A+ for(i=3D 0; i < timeout_sec; i++)=0A+ {=0A+ Sleep(1000);= =0A+ if(IsDebuggerPresent())=0A+ {=0A+ /* Break into= debugger */=0A+ __debugbreak();=0A+ return;=0A+ }= =0A+ }=0A+ printf("pid=3D%u, debugger not attached after %d seconds,= resuming\n",GetCurrentProcessId(),=0A+ timeout_sec);=0A+ fflush(stdout);= =0A+ }=0A+}=0A+#endif /* DEBUG_UNHANDLED_EXCEPTION_FILTER */=0A+=0A+LONG= WINAPI my_unhandler_exception_filter(EXCEPTION_POINTERS *ex_pointers)=0A+{= =0A+ static BOOL first_time=3D TRUE;=0A+ if(!first_time)=0A+ {=0A+= /*=0A+ This routine can be called twice, typically=0A+ = when detaching in JIT debugger.=0A+ Return EXCEPTION_EXECUTE_HANDLER= to terminate process.=0A+ */=0A+ return EXCEPTION_EXECUTE_HANDLER;= =0A+ }=0A+ first_time=3D FALSE;=0A+#ifdef DEBUG_UNHANDLED_EXCEPTION_FILTER= =0A+ /*=0A+ Unfortunately there is no clean way to debug unhandled= exception filters,=0A+ as debugger does not stop there(also documented= in MSDN) =0A+ To overcome, one could put a MessageBox, but this will= not work in service.=0A+ Better solution is to print error message and= sleep some minutes =0A+ until debugger is attached=0A+ */=0A+ wait_for_debugger(DEBUGGER_ATTACH_TIMEOUT);= =0A+#endif /* DEBUG_UNHANDLED_EXCEPTION_FILTER */=0A+ __try=0A+ {=0A+= set_exception_pointers(ex_pointers);=0A+ handle_segfault(ex_pointers->ExceptionRecord->ExceptionCode);= =0A+ }=0A+ __except(EXCEPTION_EXECUTE_HANDLER)=0A+ {=0A+ DWORD written;= =0A+ const char msg[] =3D "Got exception in exception handler!\n";=0A+= WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),msg, sizeof(msg)-1, =0A+ = &written,NULL);=0A+ }=0A+ /*=0A+ Return EXCEPTION_CONTINUE_SEARCH= to give JIT debugger=0A+ (drwtsn32 or vsjitdebugger) possibility to= attach,=0A+ if JIT debugger is configured.=0A+ Windows Error reporting= might generate a dump here.=0A+ */=0A+ return EXCEPTION_CONTINUE_SEARCH;= =0A }=0A =0A+=0A+static void init_signals(void)=0A+{=0A+ win_install_sigabrt_handler();= =0A+ if(opt_console)=0A+ SetConsoleCtrlHandler(console_event_handler,TRUE);= =0A+ else=0A+ {=0A+ /* Avoid MessageBox()es*/=0A+ _CrtSetReportMode(_CRT_WARN,= _CRTDBG_MODE_FILE);=0A+ _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);= =0A+ _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);=0A+ _CrtSetReportFile(_CRT_ERROR,= _CRTDBG_FILE_STDERR);=0A+ _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);= =0A+ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);=0A+=0A+ /*= =0A+ Do not use SEM_NOGPFAULTERRORBOX in the following SetErrorMode= (),=0A+ because it would prevent JIT debugger and Windows error reporting= =0A+ from working. We need WER or JIT-debugging, since our own unhandled= =0A+ exception filter is not guaranteed to work in all situation=0A+= (like heap corruption or stack overflow)=0A+ */=0A+ SetErrorMode(SetErrorMode(0)|SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);= =0A+ }=0A+ SetUnhandledExceptionFilter(my_unhandler_exception_filter);= =0A+}=0A+=0A+=0A static void start_signal_handler(void)=0A {=0A // Save= vm id of this process=0A@@ -2094,8 +2236,8 @@ static void start_signal_handler(void)= =0A =0A static void check_data_home(const char *path)=0A {}=0A+#endif=0A= =0A-#else /* if ! __WIN__ && ! __EMX__ */=0A =0A #ifdef HAVE_LINUXTHREADS= =0A #define UNSAFE_DEFAULT_LINUX_THREADS 200=0A@@ -2125,7 +2267,7 @@ extern= "C" sig_handler handle_segfault(i=0A localtime_r(&curr_time, &tm);=0A= =0A fprintf(stderr,"\=0A-%02d%02d%02d %2d:%02d:%02d - mysqld got signal= %d;\n\=0A+%02d%02d%02d %2d:%02d:%02d - mysqld got " SIGNAL_FMT " ;\n\=0A= This could be because you hit a bug. It is also possible that this binary\n\= =0A or one of the libraries it was linked against is corrupt, improperly= built,\n\=0A or misconfigured. This error can also be caused by malfunctioning= hardware.\n",=0A@@ -2166,6 +2308,10 @@ the thread stack. Please read http://dev= =0A if (!(test_flags & TEST_NO_STACKTRACE))=0A {=0A fprintf(stderr,"thd=3D%p\n",thd);= =0A+ fprintf(stderr,"\=0A+Attempting backtrace. You can use the following= information to find out\n\=0A+where mysqld died. If you see no messages= after this, something went\n\=0A+terribly wrong...\n");=0A print_stacktrace(thd= ? (gptr) thd->thread_stack : (gptr) 0,=0A thread_stack);=0A }= =0A@@ -2214,15 +2360,22 @@ of those buggy OS calls. You should con=0A bugs.\n");= =0A }=0A =0A+#ifdef HAVE_WRITE_CORE=0A if (test_flags & TEST_CORE_ON_SIGNAL)= =0A {=0A fprintf(stderr, "Writing a core file\n");=0A fflush(stderr);= =0A write_core(sig);=0A }=0A+#endif=0A+=0A+#ifndef __WIN__=0A+ /*= On Windows, do not terminate, but pass control to exception filter */=0A= exit(1);=0A+#endif=0A }=0A =0A+#if !defined(__WIN__) && !defined(__NETWARE__)= && !defined(__EMX__)=0A #ifndef SA_RESETHAND=0A #define SA_RESETHAND 0= =0A #endif=0A@@ -2567,19 +2720,6 @@ static void my_str_free_mysqld(void= *ptr=0A =0A =0A #ifdef __WIN__=0A-=0A-struct utsname=0A-{=0A- char nodename[FN_REFLEN];= =0A-};=0A-=0A-=0A-int uname(struct utsname *a)=0A-{=0A- return -1;=0A-}= =0A-=0A-=0A pthread_handler_t handle_shutdown(void *arg)=0A {=0A MSG msg;= =0A@@ -2593,18 +2733,6 @@ pthread_handler_t handle_shutdown(void *=0A = kill_server(MYSQL_KILL_SIGNAL);=0A return 0;=0A }=0A-=0A-=0A-int STDCALL= handle_kill(ulong ctrl_type)=0A-{=0A- if (ctrl_type =3D=3D CTRL_CLOSE_EVENT= ||=0A- ctrl_type =3D=3D CTRL_SHUTDOWN_EVENT)=0A- {=0A- kill_server(MYSQL_KILL_SIGNAL);= =0A- return TRUE;=0A- }=0A- return FALSE;=0A-}=0A #endif=0A =0A =0A@@= -3632,11 +3760,6 @@ we force server id to 2, but this MySQL =0A freopen(log_error_file,"a+",stdout);= =0A freopen(log_error_file,"a+",stderr);=0A FreeConsole(); //= Remove window=0A- }=0A- else=0A- {=0A- /* Don't show error dialog= box when on foreground: it stops the server */ =0A- SetErrorMode(SEM_NOOPENFILEERRORBOX= | SEM_FAILCRITICALERRORS);=0A }=0A #endif=0A =0Adiff -Nrup a/sql/sql_parse.cc= b/sql/sql_parse.cc=0A--- a/sql/sql_parse.cc 2007-12-10 12:19:46 +01:00= =0A+++ b/sql/sql_parse.cc 2008-02-18 10:51:22 +01:00=0A@@ -98,22 +98,7 @@= static bool do_command(THD *thd);=0A #endif // EMBEDDED_LIBRARY=0A =0A= #ifdef __WIN__=0A-static void test_signal(int sig_ptr)=0A-{=0A-#if !defined(= DBUG_OFF)=0A- MessageBox(NULL,"Test signal","DBUG",MB_OK);=0A-#endif=0A-#if= defined(OS2)=0A- fprintf(stderr, "Test signal %d\n", sig_ptr);=0A- fflush(stderr);= =0A-#endif=0A-}=0A-static void init_signals(void)=0A-{=0A- int signals[7]= =3D {SIGINT,SIGILL,SIGFPE,SIGSEGV,SIGTERM,SIGBREAK,SIGABRT } ;=0A- for= (int i=3D0 ; i < 7 ; i++)=0A- signal( signals[i], test_signal) ;=0A-}= =0A+extern void win_install_sigabrt_handler(void);=0A #endif=0A =0A static= void unlock_locked_tables(THD *thd)=0A@@ -1124,7 +1109,7 @@ pthread_handler_t= handle_one_connection(=0A /* now that we've called my_thread_init(),= it is safe to call DBUG_* */=0A =0A #if defined(__WIN__)=0A- init_signals();= =0A+ win_install_sigabrt_handler();=0A #elif !defined(OS2) && !defined(__NETWARE__)= =0A sigset_t set;=0A VOID(sigemptyset(&set)); // Get mask in use=0Adiff= -Nrup a/sql/stacktrace.c b/sql/stacktrace.c=0A--- a/sql/stacktrace.c 2007-07-07= 07:46:14 +02:00=0A+++ b/sql/stacktrace.c 2008-02-18 10:51:22 +01:00=0A@@= -13,11 +13,15 @@=0A along with this program; if not, write to the Free= Software=0A Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA= 02111-1307 USA */=0A =0A+/* Workaround for Bug#32082: VOID redefinition= on Win results in compile errors*/=0A+#define DONT_DEFINE_VOID 1=0A+=0A= #include =0A #include "stacktrace.h"=0A+=0A+#ifndef __WIN__= =0A #include =0A #include =0A-=0A #ifdef HAVE_STACKTRACE= =0A #include =0A #include =0A@@ -118,10 +122,7 @@ void= print_stacktrace(gptr stack_bottom=0A #endif=0A LINT_INIT(fp);=0A =0A-= fprintf(stderr,"\=0A-Attempting backtrace. You can use the following information= to find out\n\=0A-where mysqld died. If you see no messages after this,= something went\n\=0A-terribly wrong...\n");=0A+=0A #ifdef __i386__=0A = __asm __volatile__ ("movl %%ebp,%0"=0A :"=3Dr"(fp)=0A@@ -257,3= +258,255 @@ void write_core(int sig)=0A #endif=0A }=0A #endif=0A+#else= /* __WIN__*/=0A+=0A+#include =0A+=0A+/*=0A+ Stack tracing on= Windows is implemented using Debug Helper library(dbghelp.dll)=0A+ We= do not redistribute dbghelp and the one comes with older OS (up to Windows= 2000)=0A+ is missing some important functions like functions StackWalk64= or MinidumpWriteDump.=0A+ Hence, we have to load functions at runtime= using LoadLibrary/GetProcAddress.=0A+*/=0A+=0A+typedef DWORD (WINAPI *SymSetOptions_FctType)(DWORD= dwOptions);=0A+typedef BOOL (WINAPI *SymGetModuleInfo64_FctType)=0A+ = (HANDLE,DWORD64,PIMAGEHLP_MODULE64) ;=0A+typedef BOOL (WINAPI *SymGetSymFromAddr64_FctType)= =0A+ (HANDLE,DWORD64,PDWORD64,PIMAGEHLP_SYMBOL64) ;=0A+typedef BOOL (WINAPI= *SymGetLineFromAddr64_FctType)=0A+ (HANDLE,DWORD64,PDWORD,PIMAGEHLP_LINE64);= =0A+typedef BOOL (WINAPI *SymInitialize_FctType)=0A+ (HANDLE,PSTR,BOOL);= =0A+typedef BOOL (WINAPI *StackWalk64_FctType)=0A+ (DWORD,HANDLE,HANDLE,LPSTACKFRAME64,PVOID,PREAD_PROCESS_MEMORY_ROUTINE64,= =0A+ PFUNCTION_TABLE_ACCESS_ROUTINE64,PGET_MODULE_BASE_ROUTINE64 ,=0A+= PTRANSLATE_ADDRESS_ROUTINE64);=0A+typedef BOOL (WINAPI *MiniDumpWriteDump_FctType)(= =0A+ IN HANDLE hProcess,=0A+ IN DWORD ProcessId,=0A+ IN HANDLE= hFile,=0A+ IN MINIDUMP_TYPE DumpType,=0A+ IN CONST PMINIDUMP_EXCEPTION_INFORMATION= ExceptionParam, OPTIONAL=0A+ IN CONST PMINIDUMP_USER_STREAM_INFORMATION= UserStreamParam, OPTIONAL=0A+ IN CONST PMINIDUMP_CALLBACK_INFORMATION= CallbackParam OPTIONAL=0A+ );=0A+=0A+static SymSetOptions_FctType = pSymSetOptions;=0A+static SymGetModuleInfo64_FctType pSymGetModuleInfo64;= =0A+static SymGetSymFromAddr64_FctType pSymGetSymFromAddr64;=0A+static= SymInitialize_FctType pSymInitialize;=0A+static StackWalk64_FctType= pStackWalk64;=0A+static SymGetLineFromAddr64_FctType pSymGetLineFromAddr64;= =0A+static MiniDumpWriteDump_FctType pMiniDumpWriteDump;=0A+=0A+static= EXCEPTION_POINTERS *exception_ptrs;=0A+=0A+#define MODULE64_SIZE_WINXP= 576=0A+#define STACKWALK_MAX_FRAMES 64=0A+=0A+/*=0A+ Dynamically load= dbghelp functions=0A+*/=0A+BOOL init_dbghelp_functions()=0A+{=0A+ static= BOOL first_time=3DTRUE;=0A+ static BOOL rc;=0A+ HMODULE hDbghlp;=0A+= =0A+ if(first_time)=0A+ {=0A+ first_time=3D FALSE;=0A+ hDbghlp=3D= LoadLibrary("dbghelp");=0A+ if(!hDbghlp)=0A+ {=0A+ rc=3D FALSE;= =0A+ return rc;=0A+ }=0A+ pSymSetOptions=3D (SymSetOptions_FctType)= =0A+ GetProcAddress(hDbghlp,"SymSetOptions");=0A+ pSymInitialize=3D= (SymInitialize_FctType)=0A+ GetProcAddress(hDbghlp,"SymInitialize");= =0A+ pSymGetModuleInfo64=3D (SymGetModuleInfo64_FctType)=0A+ GetProcAddress(hDbghlp,"SymGetModuleInfo64");= =0A+ pSymGetLineFromAddr64=3D (SymGetLineFromAddr64_FctType)=0A+ = GetProcAddress(hDbghlp,"SymGetLineFromAddr64");=0A+ pSymGetSymFromAddr64=3D(SymGetSymFromAddr64_FctType)= =0A+ GetProcAddress(hDbghlp,"SymGetSymFromAddr64");=0A+ pStackWalk64=3D= (StackWalk64_FctType)=0A+ GetProcAddress(hDbghlp,"StackWalk64");=0A+= pMiniDumpWriteDump =3D (MiniDumpWriteDump_FctType)=0A+ GetProcAddress(hDbghlp,"MiniDumpWriteDump");= =0A+=0A+ rc =3D (BOOL)(pSymSetOptions && pSymInitialize && pSymGetModuleInfo64= =0A+ && pSymGetLineFromAddr64 && pSymGetSymFromAddr64 && pStackWalk64);= =0A+ }=0A+ return rc;=0A+}=0A+=0A+void set_exception_pointers(EXCEPTION_POINTERS= *ep)=0A+{=0A+ exception_ptrs =3D ep;=0A+}=0A+=0A+/* Platform SDK in VS2003= does not have definition for SYMOPT_NO_PROMPTS*/=0A+#ifndef SYMOPT_NO_PROMPTS= =0A+#define SYMOPT_NO_PROMPTS 0=0A+#endif=0A+=0A+void print_stacktrace(gptr= unused1, ulong unused2)=0A+{=0A+ HANDLE hProcess=3D GetCurrentProcess();= =0A+ HANDLE hThread=3D GetCurrentThread();=0A+ static IMAGEHLP_MODULE64= module=3D {sizeof(module)};=0A+ static IMAGEHLP_SYMBOL64_PACKAGE package;= =0A+ DWORD64 addr;=0A+ DWORD machine;=0A+ int i;=0A+ CONTEXT context;= =0A+ STACKFRAME64 frame=3D{0};=0A+=0A+ /*Initialize symbols.*/=0A+ if(!exception_ptrs= || !init_dbghelp_functions())=0A+ return;=0A+=0A+ /* Copy context,= as stackwalking on original will unwind the stack */=0A+ context =3D *(exception_ptrs->ContextRecord);= =0A+ pSymSetOptions(SYMOPT_LOAD_LINES|SYMOPT_NO_PROMPTS|SYMOPT_DEFERRED_LOADS|SYMOPT_DEBUG);= =0A+ pSymInitialize(hProcess,NULL,TRUE);=0A+=0A+ /*Prepare stackframe= for the StackWalk64 first call*/=0A+ frame.AddrFrame.Mode =3D frame.AddrPC.Mode= =3D frame.AddrStack.Mode =3D AddrModeFlat;=0A+#if (defined _M_IX86)=0A+= machine=3D IMAGE_FILE_MACHINE_I386;=0A+ frame.AddrFrame.Offset=3D context.Ebp;= =0A+ frame.AddrPC.Offset=3D context.Eip;=0A+ frame.AddrStack.Offset=3D= context.Esp;=0A+#elif (defined _M_X64)=0A+ machine =3D IMAGE_FILE_MACHINE_AMD64;= =0A+ frame.AddrFrame.Offset=3D context.Rbp;=0A+ frame.AddrPC.Offset=3D= context.Rip;=0A+ frame.AddrStack.Offset=3D context.Rsp;=0A+#else=0A+= /*There is currently no need to support IA64*/=0A+#pragma error ("unsupported= architecture")=0A+#endif=0A+=0A+ package.sym.SizeOfStruct=3D sizeof(package.sym);= =0A+ package.sym.MaxNameLength=3D sizeof(package.name);=0A+=0A+ /*Walk= the stack, output useful information*/ =0A+ for(i=3D 0; i< STACKWALK_MAX_FRAMES;i++)= =0A+ {=0A+ DWORD64 function_offset=3D 0;=0A+ DWORD line_offset=3D= 0;=0A+ IMAGEHLP_LINE64 line=3D {sizeof(line)};=0A+ BOOL have_module=3D= FALSE;=0A+ BOOL have_symbol=3D FALSE;=0A+ BOOL have_source=3D FALSE;= =0A+=0A+ if(!pStackWalk64(machine, hProcess, hThread, &frame, &context,= 0, 0, 0 ,0))=0A+ break;=0A+ addr=3D frame.AddrPC.Offset;=0A+=0A+= have_module=3D pSymGetModuleInfo64(hProcess,addr,&module);=0A+#ifdef= _M_IX86=0A+ if(!have_module)=0A+ {=0A+ /*=0A+ ModuleInfo= structure has been "compatibly" extended in releases after XP,=0A+ = and its size was increased. To make XP dbghelp.dll function=0A+ = happy, pretend passing the old structure.=0A+ */=0A+ module.SizeOfStruct=3D= MODULE64_SIZE_WINXP;=0A+ have_module=3D pSymGetModuleInfo64(hProcess,= addr, &module);=0A+ }=0A+#endif=0A+=0A+ have_symbol=3D pSymGetSymFromAddr64(hProcess,= addr, &function_offset,=0A+ &(package.sym));=0A+ have_source=3D= pSymGetLineFromAddr64(hProcess, addr, &line_offset, &line);=0A+=0A+ = fprintf(stderr, "%p ", addr);=0A+ if(have_module)=0A+ {=0A+ = char *base_image_name=3D strrchr(module.ImageName, '\\');=0A+ if(base_image_name)= =0A+ base_image_name++;=0A+ else=0A+ base_image_name=3D= module.ImageName;=0A+ fprintf(stderr, "%s!", base_image_name);=0A+= }=0A+ if(have_symbol)=0A+ fprintf(stderr, "%s()", package.sym.Name);= =0A+ else if(have_module)=0A+ fprintf(stderr, "???");=0A+=0A+ = if(have_source)=0A+ {=0A+ char *base_file_name=3D strrchr(line.FileName,= '\\');=0A+ if(base_file_name)=0A+ base_file_name++;=0A+ = else=0A+ base_file_name=3D line.FileName;=0A+ fprintf(stderr,"[%s:%u]",= base_file_name, line.LineNumber);=0A+ }=0A+ fprintf(stderr, "\n");= =0A+ }=0A+ fflush(stderr);=0A+}=0A+=0A+=0A+/*=0A+ Write dump. The dump= is created in current directory,=0A+ file name is constructed from executable= name plus=0A+ ".dmp" extension=0A+*/=0A+void write_core(int unused)=0A+{= =0A+ char path[MAX_PATH];=0A+ char dump_fname[MAX_PATH];=0A+ MINIDUMP_EXCEPTION_INFORMATION= info;=0A+ HANDLE hFile;=0A+=0A+ if(!exception_ptrs || !init_dbghelp_functions()= || !pMiniDumpWriteDump)=0A+ return;=0A+=0A+ info.ExceptionPointers=3D= exception_ptrs;=0A+ info.ClientPointers=3D FALSE;=0A+ info.ThreadId=3D= GetCurrentThreadId();=0A+=0A+ if(!GetModuleFileName(NULL, path, sizeof(path)))= =0A+ return;=0A+ _splitpath(path, NULL, NULL,dump_fname,NULL);=0A+ = strncat(dump_fname, ".dmp", sizeof(dump_fname));=0A+=0A+ hFile=3D CreateFile(dump_fname,= GENERIC_WRITE, 0, 0, CREATE_ALWAYS,=0A+ FILE_ATTRIBUTE_NORMAL, 0);=0A+= if(!hFile)=0A+ return;=0A+=0A+ /* Create minidump */=0A+ if(pMiniDumpWriteDump(GetCurrentProcess(),= GetCurrentProcessId(),=0A+ hFile, MiniDumpNormal, &info, 0, 0))=0A+= {=0A+ fprintf(stderr, "Minidump written to %s\n",=0A+ _fullpath(path,= dump_fname, sizeof(path)) ? path : dump_fname);=0A+ }=0A+ CloseHandle(hFile);= =0A+}=0A+=0A+=0A+void safe_print_str(const char *name, const char *val,= int len)=0A+{=0A+ fprintf(stderr,"%s at %p", name, val);=0A+ __try =0A+= {=0A+ fprintf(stderr,"=3D%.*s\n", len, val);=0A+ }=0A+ __except(EXCEPTION_EXECUTE_HANDLER)= =0A+ {=0A+ fprintf(stderr,"is an invalid string pointer\n");=0A+ }= =0A+}=0A+#endif /*_WIN32*/=0Adiff -Nrup a/sql/stacktrace.h b/sql/stacktrace.h= =0A--- a/sql/stacktrace.h 2006-12-23 20:04:28 +01:00=0A+++ b/sql/stacktrace.h= 2008-02-18 10:51:23 +01:00=0A@@ -29,20 +29,33 @@ extern char* heap_start;= =0A heap_start =3D (char*) &__bss_start; \=0A= check_thread_lib(); \=0A = } while(0);=0A+void check_thread_lib(void);=0A+#endif= /* defined (__i386__) || (defined(__alpha__) && defined(__GNUC__))) */= =0A+#elif defined (__WIN__)=0A+#define HAVE_STACKTRACE=0A+extern void set_exception_pointers(EXCEPTION_POINTERS= *ep);=0A+#define init_stacktrace() {}=0A+#endif=0A+=0A+#ifdef HAVE_STACKTRACE= =0A void print_stacktrace(gptr stack_bottom, ulong thread_stack);=0A void= safe_print_str(const char* name, const char* val, int max_len);=0A-void= check_thread_lib(void); =0A-#endif /* (defined (__i386__) || (defined(__alpha__)= && defined(__GNUC__))) */=0A-#endif /* TARGET_OS_LINUX */=0A-=0A+#else= =0A /* Define empty prototypes for functions that are not implemented */= =0A-#ifndef HAVE_STACKTRACE=0A #define init_stacktrace() {}=0A #define print_stacktrace(A,B)= {}=0A #define safe_print_str(A,B,C) {}=0A #endif /* HAVE_STACKTRACE */= =0A =0A+=0A+#if !defined(__NETWARE__)=0A+#define HAVE_WRITE_CORE=0A+#endif= =0A+=0A+#ifdef HAVE_WRITE_CORE=0A void write_core(int sig);=0A+#endif=0A+= =0A =0A #ifdef __cplusplus=0A }=0A