List:Commits« Previous MessageNext Message »
From:msvensson Date:October 22 2007 3:10pm
Subject:bk commit into 5.0 tree (msvensson:1.2530) BUG#31745
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of msvensson. When msvensson does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2007-10-22 15:10:06+02:00, msvensson@shellback.(none) +3 -0
  Bug#31745 mysqld crash handler does not work on windows
  - Rework signal handler code to either shutdown using the shutdown
    thread or call 'handle_segfault' to print out crash info and then
    crash the mysqld

  sql/mysqld.cc@stripped, 2007-10-22 15:10:03+02:00, msvensson@shellback.(none) +256 -183
    - Improve comments and error message for the windows specific
      shutdown code.
    - Remove the patch for bug#18325, it's not needed now when the
      shutdown thread does the shutdown.
    - Move the 'handle_segfault' function so it can be used on all
      platforms when a fatal error has occured.
    - Change the windows implementation of 'init_signal' to install one
      common signal handler 'handle_win_signal' for all signals that
      should be handled.
    - Add signal handler 'handle_win_signal' for windows
      which will perform "ordered shutdown" for SIGINT and "hard shutdown"
      using 'handle_segault' function otherwise.
    - Remove unused functions 'utsname', 'uname' and 'handle_kill'

  sql/sql_parse.cc@stripped, 2007-10-22 15:10:04+02:00, msvensson@shellback.(none) +5 -18
    Use the 'init_signals' function in mysqld.cc to init per thread 
    signal handlers when running on windows

  sql/stacktrace.h@stripped, 2007-10-22 15:10:04+02:00, msvensson@shellback.(none) +5 -0
    Don't declare 'write_core' on windows
    Add define HAVE_WRITECORE to be defined if 'write_core' function
    is available

diff -Nrup a/sql/mysqld.cc b/sql/mysqld.cc
--- a/sql/mysqld.cc	2007-10-02 11:34:29 +02:00
+++ b/sql/mysqld.cc	2007-10-22 15:10:03 +02:00
@@ -580,7 +580,7 @@ static int opt_argc;
 static char **opt_argv;
 
 #if !defined(EMBEDDED_LIBRARY)
-static HANDLE hEventShutdown;
+static HANDLE hEventShutdown= 0;
 static char shutdown_event_name[40];
 #include "nt_servc.h"
 static	 NTService  Service;	      // Service object for WinNT
@@ -921,17 +921,11 @@ void kill_mysql(void)
 
 #if defined(__WIN__)
 #if !defined(EMBEDDED_LIBRARY)
+  /* Release the shutdown thread */
+  if (!SetEvent(hEventShutdown))
   {
-    if (!SetEvent(hEventShutdown))
-    {
-      DBUG_PRINT("error",("Got error: %ld from SetEvent",GetLastError()));
-    }
-    /*
-      or:
-      HANDLE hEvent=OpenEvent(0, FALSE, "MySqlShutdown");
-      SetEvent(hEventShutdown);
-      CloseHandle(hEvent);
-    */
+    DBUG_PRINT("error",("%s", _strerror("Got error when signaling "
+                                        "shutdown thread")));
   }
 #endif
 #elif defined(OS2)
@@ -1001,14 +995,11 @@ static void __cdecl kill_server(int sig_
     sql_print_error(ER(ER_GOT_SIGNAL),my_progname,sig); /* purecov: inspected */
 
 #if defined(HAVE_SMEM) && defined(__WIN__)
-  /*
-   Send event to smem_event_connect_request for aborting
-   */
+  /* Break the wait for shared memory connections */
   if (!SetEvent(smem_event_connect_request))
   {
-	  DBUG_PRINT("error",
-		("Got error: %ld from SetEvent of smem_event_connect_request",
-		 GetLastError()));
+    DBUG_PRINT("error",("%s", _strerror("Got error when signaling the connect"
+                                        "thread for shared memory")));
   }
 #endif
 
@@ -1016,11 +1007,7 @@ static void __cdecl kill_server(int sig_
   my_thread_init();				// If this is a new thread
 #endif
   close_connections();
-  if (sig != MYSQL_KILL_SIGNAL &&
-#ifdef __WIN__
-      sig != SIGINT &&				/* Bug#18235 */
-#endif
-      sig != 0)
+  if (sig != MYSQL_KILL_SIGNAL && sig != 0)
     unireg_abort(1);				/* purecov: inspected */
   else
     unireg_end();
@@ -1776,25 +1763,253 @@ extern "C" sig_handler abort_thread(int 
 #endif
 
 /******************************************************************************
-  Setup a signal thread with handles all signals.
-  Because Linux doesn't support schemas use a mutex to check that
-  the signal thread is ready before continuing
+  Setup of signal handling
 ******************************************************************************/
 
 
+/*
+  handle_segfault
+
+  Generic function to call when server has caught a fatal signal
+*/
+
+extern "C" sig_handler handle_segfault(int sig)
+{
+  time_t curr_time;
+  struct tm tm;
+  THD *thd= current_thd;
+
+  /*
+    Strictly speaking, one needs a mutex here
+    but since we have got SIGSEGV already, things are a mess
+    so not having the mutex is not as bad as possibly using a buggy
+    mutex - so we keep things simple
+  */
+  if (segfaulted)
+  {
+    fprintf(stderr, "Fatal signal %d while backtracing\n", sig);
+    exit(1);
+  }
+
+  segfaulted= 1;
+
+  curr_time= time(NULL);
+  localtime_r(&curr_time, &tm);
+
+  fprintf(stderr,"\
+%02d%02d%02d %2d:%02d:%02d - mysqld got signal %d;\n\
+This could be because you hit a bug. It is also possible that this binary\n\
+or one of the libraries it was linked against is corrupt, improperly built,\n\
+or misconfigured. This error can also be caused by malfunctioning hardware.\n",
+          tm.tm_year % 100, tm.tm_mon+1, tm.tm_mday,
+          tm.tm_hour, tm.tm_min, tm.tm_sec,
+	  sig);
+  fprintf(stderr, "\
+We will try our best to scrape up some info that will hopefully help diagnose\n\
+the problem, but since we have already crashed, something is definitely wrong\n\
+and this may fail.\n\n");
+  fprintf(stderr, "key_buffer_size=%lu\n",
+          (ulong) dflt_key_cache->key_cache_mem_size);
+  fprintf(stderr, "read_buffer_size=%ld\n", (long) global_system_variables.read_buff_size);
+  fprintf(stderr, "max_used_connections=%lu\n", max_used_connections);
+  fprintf(stderr, "max_connections=%lu\n", max_connections);
+  fprintf(stderr, "threads_connected=%u\n", thread_count);
+  fprintf(stderr, "It is possible that mysqld could use up to \n\
+key_buffer_size + (read_buffer_size + sort_buffer_size)*max_connections = %lu K\n\
+bytes of memory\n", ((ulong) dflt_key_cache->key_cache_mem_size +
+		     (global_system_variables.read_buff_size +
+		      global_system_variables.sortbuff_size) *
+		     max_connections)/ 1024);
+  fprintf(stderr, "Hope that's ok; if not, decrease some variables in the equation.\n\n");
+
+#if defined(HAVE_LINUXTHREADS)
+#define UNSAFE_DEFAULT_LINUX_THREADS 200
+  if (sizeof(char*) == 4 && thread_count > UNSAFE_DEFAULT_LINUX_THREADS)
+  {
+    fprintf(stderr, "\
+You seem to be running 32-bit Linux and have %d concurrent connections.\n\
+If you have not changed STACK_SIZE in LinuxThreads and built the binary \n\
+yourself, LinuxThreads is quite likely to steal a part of the global heap for\n\
+the thread stack. Please read http://www.mysql.com/doc/en/Linux.html\n\n",
+	    thread_count);
+  }
+#endif /* HAVE_LINUXTHREADS */
+
+#ifdef HAVE_STACKTRACE
+  if (!(test_flags & TEST_NO_STACKTRACE))
+  {
+    fprintf(stderr,"thd=%p\n",thd);
+    print_stacktrace(thd ? (gptr) thd->thread_stack : (gptr) 0,
+		     thread_stack);
+  }
+  if (thd)
+  {
+    fprintf(stderr, "Trying to get some variables.\n\
+Some pointers may be invalid and cause the dump to abort...\n");
+    safe_print_str("thd->query", thd->query, 1024);
+    fprintf(stderr, "thd->thread_id=%lu\n", (ulong) thd->thread_id);
+  }
+  fprintf(stderr, "\
+The manual page at http://www.mysql.com/doc/en/Crashing.html contains\n\
+information that should help you find out what is causing the crash.\n");
+  fflush(stderr);
+#endif /* HAVE_STACKTRACE */
+
+#ifdef HAVE_INITGROUPS
+  if (calling_initgroups)
+    fprintf(stderr, "\n\
+This crash occured while the server was calling initgroups(). This is\n\
+often due to the use of a mysqld that is statically linked against glibc\n\
+and configured to use LDAP in /etc/nsswitch.conf. You will need to either\n\
+upgrade to a version of glibc that does not have this problem (2.3.4 or\n\
+later when used with nscd), disable LDAP in your nsswitch.conf, or use a\n\
+mysqld that is not statically linked.\n");
+#endif
+
+#ifdef HAVE_NPTL
+  if (thd_lib_detected == THD_LIB_LT && !getenv("LD_ASSUME_KERNEL"))
+    fprintf(stderr,"\n\
+You are running a statically-linked LinuxThreads binary on an NPTL system.\n\
+This can result in crashes on some distributions due to LT/NPTL conflicts.\n\
+You should either build a dynamically-linked binary, or force LinuxThreads\n\
+to be used with the LD_ASSUME_KERNEL environment variable. Please consult\n\
+the documentation for your distribution on how to do that.\n");
+#endif
+
+  if (locked_in_memory)
+  {
+    fprintf(stderr, "\n\
+The \"--memlock\" argument, which was enabled, uses system calls that are\n\
+unreliable and unstable on some operating systems and operating-system\n\
+versions (notably, some versions of Linux).  This crash could be due to use\n\
+of those buggy OS calls.  You should consider whether you really need the\n\
+\"--memlock\" parameter and/or consult the OS distributer about \"mlockall\"\n\
+bugs.\n");
+  }
+
+#ifdef HAVE_WRITECORE
+  if (test_flags & TEST_CORE_ON_SIGNAL)
+  {
+    fprintf(stderr, "Writing a core file\n");
+    fflush(stderr);
+    write_core(sig);
+  }
+#endif
+
+  exit(1);
+}
+
+
 #if defined(__WIN__) || defined(OS2)
+
+int killed_by_signal= MYSQL_KILL_SIGNAL;
+
+static void handle_win_signal(int sig)
+{
+  THD* thd= current_thd;
+
+  /*
+    NOTE!
+
+    This function is either executed by the mysql thread that
+    catch the signal(this is indicated by current_thd != NULL)
+
+    In some cases it's a new thread Windows created only
+    for handlng this signal
+
+  */
+
+  fprintf(stderr, "Got signal %d\n", sig);
+  fflush(stderr);
+
+  switch(sig)
+  {
+    /* "Nice" signal, controlled shutdown of server */
+    case SIGINT: /* aka Ctrl-C */
+      /*
+        Release the shutdown thread, it has been around
+        since the server started just waiting for the Event
+        to be signaled so it can continue and call kill_server
+      */
+      killed_by_signal= sig;
+      if (SetEvent(hEventShutdown) == 0)
+      {
+        /*
+          Failed to release the shutdown thread - maybe
+          the Event has already been closed or is not yet created.
+          Take down the system hard
+        */
+        exit(1);
+      }
+    break;
+
+    /* Fatal signals, print crash info and exit */
+    case SIGILL:
+    case SIGFPE:
+    case SIGSEGV:
+    case SIGTERM:
+    case SIGABRT:
+    default:
+    {
+      /* Call the fatal signal handler */
+      handle_segfault(sig);
+    }
+    break;
+  }
+
+  if (thd)
+  {
+   /*
+      End the thread if the thread has "thd" set
+
+      NOTE! It's little overkill to call end_thread
+      here in the signal handler - an alternative is to set a flag
+      on thd that skips this thread in the "close all threads loop"
+      and then let the thread enter an endless loop
+    */
+    end_thread(thd, 0); /* Never returns */
+  }
+
+  /* Don't let the signal thread end */
+  while(true)
+    Sleep(1000);
+
+}
+
+#if defined(__WIN__)
+
+/*
+  Init signal handling for windows
+
+  NOTE! All threads need to call this when they start
+
+*/
+void init_signals(void)
+{
+  int signals[] = {SIGINT,SIGILL,SIGFPE,SIGSEGV,SIGTERM,SIGABRT } ;
+  for (uint i=0 ; i < sizeof(signals)/sizeof(int) ; i++)
+    signal(signals[i], handle_win_signal) ;
+
+  /*
+    Since the mysqld should not be shutdown when user log off or
+    closes the window, SIGBREAK is ignored
+  */
+  signal(SIGBREAK,SIG_IGN);
+}
+
+#else
+
+/* OS2 */
 static void init_signals(void)
 {
   int signals[] = {SIGINT,SIGILL,SIGFPE,SIGSEGV,SIGTERM,SIGABRT } ;
   for (uint i=0 ; i < sizeof(signals)/sizeof(int) ; i++)
     signal(signals[i], kill_server) ;
-#if defined(__WIN__)
-  signal(SIGBREAK,SIG_IGN);	//ignore SIGBREAK for NT
-#else
   signal(SIGBREAK, kill_server);
-#endif
 }
 
+#endif
+
 static void start_signal_handler(void)
 {
   // Save vm id of this process
@@ -2083,132 +2298,6 @@ static void check_data_home(const char *
 
 #else /* if ! __WIN__ && ! __EMX__ */
 
-#ifdef HAVE_LINUXTHREADS
-#define UNSAFE_DEFAULT_LINUX_THREADS 200
-#endif
-
-extern "C" sig_handler handle_segfault(int sig)
-{
-  time_t curr_time;
-  struct tm tm;
-  THD *thd=current_thd;
-
-  /*
-    Strictly speaking, one needs a mutex here
-    but since we have got SIGSEGV already, things are a mess
-    so not having the mutex is not as bad as possibly using a buggy
-    mutex - so we keep things simple
-  */
-  if (segfaulted)
-  {
-    fprintf(stderr, "Fatal signal %d while backtracing\n", sig);
-    exit(1);
-  }
-
-  segfaulted = 1;
-
-  curr_time= time(NULL);
-  localtime_r(&curr_time, &tm);
-
-  fprintf(stderr,"\
-%02d%02d%02d %2d:%02d:%02d - mysqld got signal %d;\n\
-This could be because you hit a bug. It is also possible that this binary\n\
-or one of the libraries it was linked against is corrupt, improperly built,\n\
-or misconfigured. This error can also be caused by malfunctioning hardware.\n",
-          tm.tm_year % 100, tm.tm_mon+1, tm.tm_mday,
-          tm.tm_hour, tm.tm_min, tm.tm_sec,
-	  sig);
-  fprintf(stderr, "\
-We will try our best to scrape up some info that will hopefully help diagnose\n\
-the problem, but since we have already crashed, something is definitely wrong\n\
-and this may fail.\n\n");
-  fprintf(stderr, "key_buffer_size=%lu\n",
-          (ulong) dflt_key_cache->key_cache_mem_size);
-  fprintf(stderr, "read_buffer_size=%ld\n", (long) global_system_variables.read_buff_size);
-  fprintf(stderr, "max_used_connections=%lu\n", max_used_connections);
-  fprintf(stderr, "max_connections=%lu\n", max_connections);
-  fprintf(stderr, "threads_connected=%u\n", thread_count);
-  fprintf(stderr, "It is possible that mysqld could use up to \n\
-key_buffer_size + (read_buffer_size + sort_buffer_size)*max_connections = %lu K\n\
-bytes of memory\n", ((ulong) dflt_key_cache->key_cache_mem_size +
-		     (global_system_variables.read_buff_size +
-		      global_system_variables.sortbuff_size) *
-		     max_connections)/ 1024);
-  fprintf(stderr, "Hope that's ok; if not, decrease some variables in the equation.\n\n");
-
-#if defined(HAVE_LINUXTHREADS)
-  if (sizeof(char*) == 4 && thread_count > UNSAFE_DEFAULT_LINUX_THREADS)
-  {
-    fprintf(stderr, "\
-You seem to be running 32-bit Linux and have %d concurrent connections.\n\
-If you have not changed STACK_SIZE in LinuxThreads and built the binary \n\
-yourself, LinuxThreads is quite likely to steal a part of the global heap for\n\
-the thread stack. Please read http://www.mysql.com/doc/en/Linux.html\n\n",
-	    thread_count);
-  }
-#endif /* HAVE_LINUXTHREADS */
-
-#ifdef HAVE_STACKTRACE
-  if (!(test_flags & TEST_NO_STACKTRACE))
-  {
-    fprintf(stderr,"thd=%p\n",thd);
-    print_stacktrace(thd ? (gptr) thd->thread_stack : (gptr) 0,
-		     thread_stack);
-  }
-  if (thd)
-  {
-    fprintf(stderr, "Trying to get some variables.\n\
-Some pointers may be invalid and cause the dump to abort...\n");
-    safe_print_str("thd->query", thd->query, 1024);
-    fprintf(stderr, "thd->thread_id=%lu\n", (ulong) thd->thread_id);
-  }
-  fprintf(stderr, "\
-The manual page at http://www.mysql.com/doc/en/Crashing.html contains\n\
-information that should help you find out what is causing the crash.\n");
-  fflush(stderr);
-#endif /* HAVE_STACKTRACE */
-
-#ifdef HAVE_INITGROUPS
-  if (calling_initgroups)
-    fprintf(stderr, "\n\
-This crash occured while the server was calling initgroups(). This is\n\
-often due to the use of a mysqld that is statically linked against glibc\n\
-and configured to use LDAP in /etc/nsswitch.conf. You will need to either\n\
-upgrade to a version of glibc that does not have this problem (2.3.4 or\n\
-later when used with nscd), disable LDAP in your nsswitch.conf, or use a\n\
-mysqld that is not statically linked.\n");
-#endif
-
-#ifdef HAVE_NPTL
-  if (thd_lib_detected == THD_LIB_LT && !getenv("LD_ASSUME_KERNEL"))
-    fprintf(stderr,"\n\
-You are running a statically-linked LinuxThreads binary on an NPTL system.\n\
-This can result in crashes on some distributions due to LT/NPTL conflicts.\n\
-You should either build a dynamically-linked binary, or force LinuxThreads\n\
-to be used with the LD_ASSUME_KERNEL environment variable. Please consult\n\
-the documentation for your distribution on how to do that.\n");
-#endif
-  
-  if (locked_in_memory)
-  {
-    fprintf(stderr, "\n\
-The \"--memlock\" argument, which was enabled, uses system calls that are\n\
-unreliable and unstable on some operating systems and operating-system\n\
-versions (notably, some versions of Linux).  This crash could be due to use\n\
-of those buggy OS calls.  You should consider whether you really need the\n\
-\"--memlock\" parameter and/or consult the OS distributer about \"mlockall\"\n\
-bugs.\n");
-  }
-
-  if (test_flags & TEST_CORE_ON_SIGNAL)
-  {
-    fprintf(stderr, "Writing a core file\n");
-    fflush(stderr);
-    write_core(sig);
-  }
-  exit(1);
-}
-
 #ifndef SA_RESETHAND
 #define SA_RESETHAND 0
 #endif
@@ -2549,18 +2638,17 @@ static void my_str_free_mysqld(void *ptr
 
 #ifdef __WIN__
 
-struct utsname
-{
-  char nodename[FN_REFLEN];
-};
-
+/*
+  handle_shutdown
 
-int uname(struct utsname *a)
-{
-  return -1;
-}
+  This function is executed by the shutdown thread
+  that we create when the server starts.
 
+  It sole purpose is to wait for the "shutdown event"
+  to be signaled - then it willrun the code
+  in 'kill_server' to free the server resources.
 
+*/
 pthread_handler_t handle_shutdown(void *arg)
 {
   MSG msg;
@@ -2574,21 +2662,8 @@ pthread_handler_t handle_shutdown(void *
      kill_server(MYSQL_KILL_SIGNAL);
   return 0;
 }
-
-
-int STDCALL handle_kill(ulong ctrl_type)
-{
-  if (ctrl_type == CTRL_CLOSE_EVENT ||
-      ctrl_type == CTRL_SHUTDOWN_EVENT)
-  {
-    kill_server(MYSQL_KILL_SIGNAL);
-    return TRUE;
-  }
-  return FALSE;
-}
 #endif
 
-
 #ifdef OS2
 pthread_handler_t handle_shutdown(void *arg)
 {
@@ -2621,12 +2696,6 @@ static const char *load_default_groups[]
 #endif
 "mysqld","server", MYSQL_BASE_VERSION, 0, 0};
 
-#if defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
-static const int load_default_groups_sz=
-sizeof(load_default_groups)/sizeof(load_default_groups[0]);
-#endif
-
-
 /*
   Initialize one of the global date/time format variables
 
@@ -3760,6 +3829,10 @@ we force server id to 2, but this MySQL 
 ****************************************************************************/
 
 #if defined(__WIN__) && !defined(EMBEDDED_LIBRARY)
+
+static const int load_default_groups_sz=
+sizeof(load_default_groups)/sizeof(load_default_groups[0]);
+
 int mysql_service(void *p)
 {
   if (use_opt_args)
diff -Nrup a/sql/sql_parse.cc b/sql/sql_parse.cc
--- a/sql/sql_parse.cc	2007-09-03 09:22:54 +02:00
+++ b/sql/sql_parse.cc	2007-10-22 15:10:04 +02:00
@@ -93,24 +93,6 @@ const char *xa_state_names[]={
   "NON-EXISTING", "ACTIVE", "IDLE", "PREPARED"
 };
 
-#ifdef __WIN__
-static void  test_signal(int sig_ptr)
-{
-#if !defined( DBUG_OFF)
-  MessageBox(NULL,"Test signal","DBUG",MB_OK);
-#endif
-#if defined(OS2)
-  fprintf(stderr, "Test signal %d\n", sig_ptr);
-  fflush(stderr);
-#endif
-}
-static void init_signals(void)
-{
-  int signals[7] = {SIGINT,SIGILL,SIGFPE,SIGSEGV,SIGTERM,SIGBREAK,SIGABRT } ;
-  for (int i=0 ; i < 7 ; i++)
-    signal( signals[i], test_signal) ;
-}
-#endif
 
 static void unlock_locked_tables(THD *thd)
 {
@@ -1086,6 +1068,11 @@ void execute_init_command(THD *thd, sys_
   thd->net.vio= save_vio;
 }
 
+
+#ifdef __WIN__
+/* Implemented in mysqld.cc */
+void init_signals(void);
+#endif
 
 pthread_handler_t handle_one_connection(void *arg)
 {
diff -Nrup a/sql/stacktrace.h b/sql/stacktrace.h
--- a/sql/stacktrace.h	2006-12-23 20:04:28 +01:00
+++ b/sql/stacktrace.h	2007-10-22 15:10:04 +02:00
@@ -42,7 +42,12 @@ void check_thread_lib(void);  
 #define safe_print_str(A,B,C) {}
 #endif /* HAVE_STACKTRACE */
 
+#ifndef __WIN__
+
+#define HAVE_WRITECORE
 void write_core(int sig);
+
+#endif
 
 #ifdef	__cplusplus
 }
Thread
bk commit into 5.0 tree (msvensson:1.2530) BUG#31745msvensson22 Oct