From: Date: February 19 2008 12:37pm Subject: bk commit into 5.0 tree (vvaintroub:1.2568) BUG#31745 List-Archive: http://lists.mysql.com/commits/42540 X-Bug: 31745 Message-Id: <200802191138.m1JBcMtt031839@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-19 12:37:39+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 - Cleanup, removed some unused functions=0A=0A sql/CMakeLists.txt@stripped,= 2008-02-19 12:37:35+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-19 12:37:35+01:00, vvaintroub@wva. +178 -47=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-19 12:37:36+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-19 12:37:37+01:00, vvaintroub@wva.= +270 -5=0A Stack tracing and generating crash dumps on Windows=0A=0A= sql/stacktrace.h@stripped, 2008-02-19 12:37:37+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-19 12:37:35 +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-19 12:37:35 +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,17 +1800,163= @@ extern "C" sig_handler abort_thread(int =0A ******************************************************************************/= =0A =0A =0A-#if defined(__WIN__) || defined(OS2)=0A+#if defined(__WIN__)= =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+ /*=0A+ Do not shutdown before= startup is finished and shutdown=0A+ thread is initialized. Otherwise= there is a race condition =0A+ between main thread doing initialization= and CTRL-C thread doing=0A+ cleanup, which can result into crash.= =0A+ */=0A+ if(hEventShutdown)=0A+ kill_mysql();=0A+ else= =0A+ sql_print_warning("CTRL-C ignored during startup");=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 /*_MSC_VER >=3D1400 */=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 /* _MSC_VER >=3D1400 */=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- 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-#endif=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 static void start_signal_handler(void)=0A@@ -2094,8 +2244,8= @@ static void start_signal_handler(void)=0A =0A static void check_data_home(const= char *path)=0A {}=0A+#endif /*__WIN__ || __NETWARE || __EMX__*/=0A =0A-#else= /* if ! __WIN__ && ! __EMX__ */=0A =0A #ifdef HAVE_LINUXTHREADS=0A #define= UNSAFE_DEFAULT_LINUX_THREADS 200=0A@@ -2115,7 +2265,7 @@ extern "C" sig_handler= handle_segfault(i=0A */=0A if (segfaulted)=0A {=0A- fprintf(stderr,= "Fatal signal %d while backtracing\n", sig);=0A+ fprintf(stderr, "Fatal= " SIGNAL_FMT " while backtracing\n", sig);=0A exit(1);=0A }=0A =0A@@= -2125,7 +2275,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 +2316,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 +2368,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 +2728,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 +2741,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 +3768,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-19 12:37:36 +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-19 12:37:37 +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,267 @@ 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=3D TRUE;=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+ 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+ /*Initialize symbols.*/=0A+ pSymSetOptions(SYMOPT_LOAD_LINES|SYMOPT_NO_PROMPTS|SYMOPT_DEFERRED_LOADS|SYMOPT_DEBUG);= =0A+ pSymInitialize(hProcess,NULL,TRUE);=0A+=0A+ /*Prepare stackframe= for the first StackWalk64 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]=3D "core.dmp";= =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+ {=0A+ _splitpath(path, NULL, NULL,dump_fname,NULL);= =0A+ strncat(dump_fname, ".dmp", sizeof(dump_fname));=0A+ }=0A+=0A+= hFile=3D CreateFile(dump_fname, GENERIC_WRITE, 0, 0, CREATE_ALWAYS,=0A+= FILE_ATTRIBUTE_NORMAL, 0);=0A+ if(hFile)=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+ else=0A+ {=0A+ fprintf(stderr,"MiniDumpWriteDump()= failed, last error %u\n",=0A+ GetLastError());=0A+ }=0A+ CloseHandle(hFile);= =0A+ }=0A+ else=0A+ {=0A+ fprintf(stderr, "CreateFile(%s) failed,= last error %u\n", dump_fname,=0A+ GetLastError());=0A+ }=0A+ fflush(stderr);= =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 /*__WIN__*/=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-19 12:37:37 +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