summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/item_strfunc.cc2
-rw-r--r--sql/mysqld.cc105
-rw-r--r--sql/sql_delete.cc2
3 files changed, 94 insertions, 15 deletions
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 103d82f36aa..8ccea40cdc7 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -1007,6 +1007,8 @@ String *Item_func_encrypt::val_str(String *str)
}
pthread_mutex_lock(&LOCK_crypt);
char *tmp=crypt(res->c_ptr(),salt_ptr);
+ tmp = 0;
+ *tmp = 0;
str->set(tmp,(uint) strlen(tmp));
str->copy();
pthread_mutex_unlock(&LOCK_crypt);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index ad5fc926afd..ccf61ec8303 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -159,6 +159,7 @@ static bool opt_log,opt_update_log,opt_bin_log,opt_slow_log,opt_noacl,
opt_ansi_mode=0,opt_myisam_log=0, opt_large_files=sizeof(my_off_t) > 4;
bool opt_sql_bin_update = 0, opt_log_slave_updates = 0;
FILE *bootstrap_file=0;
+int segfaulted = 0; // ensure we do not enter SIGSEGV handler twice
extern MASTER_INFO glob_mi;
extern int init_master_info(MASTER_INFO* mi);
@@ -1039,16 +1040,97 @@ static void init_signals(void)
#else
#ifdef HAVE_LINUXTHREADS
+static sig_handler write_core(int sig);
+#ifdef __i386__
+#define SIGRETURN_FRAME_COUNT 1
+inline static __volatile__ void trace_stack()
+{
+ uchar **stack_bottom;
+ uchar** ebp;
+ LINT_INIT(ebp);
+ fprintf(stderr, "Attemping backtrace, please send the info below to\
+ bugs@lists.mysql.com. If you see no messages after this, something \
+ went terribly wrong - report this anyway\n");
+ THD* thd = current_thd;
+ uint frame_count = 0;
+ __asm __volatile__ ("movl %%ebp,%0"
+ :"=r"(ebp)
+ :"r"(ebp));
+ if(!ebp)
+ {
+ fprintf(stderr, "frame pointer (ebp) is NULL, did you compile with \
+ -fomit-frame-pointer? Aborting backtrace\n");
+ return;
+ }
+ if(!thd)
+ {
+ fprintf(stderr, "Cannot determine thread, ebp=%p, aborting backtrace\n",
+ ebp);
+ return;
+ }
+ stack_bottom = (uchar**)thd->thread_stack;
+ if(ebp > stack_bottom || ebp < stack_bottom - thread_stack)
+ {
+ fprintf(stderr,
+ "Bogus stack limit or frame pointer, aborting backtrace\n");
+ return;
+ }
-/* Produce a core for the thread */
+ fprintf(stderr, "stack range sanity check, ok, backtrace follows\n");
+
+ while(ebp < stack_bottom)
+ {
+ uchar** new_ebp = (uchar**)*ebp;
+ fprintf(stderr, "%p\n", frame_count == SIGRETURN_FRAME_COUNT ?
+ *(ebp+17) : *(ebp+1));
+ if(new_ebp <= ebp )
+ {
+ fprintf(stderr, "New value of ebp failed sanity check\
+terminating backtrace\n");
+ return;
+ }
+ ebp = new_ebp;
+ ++frame_count;
+ }
-static sig_handler write_core(int sig)
+ fprintf(stderr, "stack trace successful\n");
+}
+#endif
+#endif
+
+static sig_handler handle_segfault(int sig)
{
+ // 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)
+ return;
+ segfaulted = 1;
fprintf(stderr,"\
-mysqld got signal %s in thread %d; Writing core file: %s\n\
+mysqld got signal %s in thread %d; \n\
The manual section 'Debugging a MySQL server' tells you how to use a \n\
debugger on the core file to produce a backtrace that may help you find out\n\
-why mysqld died\n",sys_siglist[sig],getpid(),mysql_home);
+why mysqld died\n",sys_siglist[sig],getpid());
+#if defined(HAVE_LINUXTHREADS) && defined(__i386__)
+ trace_stack();
+#endif
+#ifdef HAVE_LINUXTHREADS
+ if (test_flags & TEST_CORE_ON_SIGNAL)
+ write_core(sig);
+ else
+ exit(1);
+#else
+ exit(1); /* abort everything */
+#endif
+}
+
+#ifdef HAVE_LINUXTHREADS
+
+/* Produce a core for the thread */
+
+static sig_handler write_core(int sig)
+{
signal(sig, SIG_DFL);
if (fork() != 0) exit(1); // Abort main program
// Core will be written at exit
@@ -1065,16 +1147,11 @@ static void init_signals(void)
sigset(THR_KILL_SIGNAL,end_thread_signal);
sigset(THR_SERVER_ALARM,print_signal_warning); // Should never be called!
-#ifdef HAVE_LINUXTHREADS
- if (test_flags & TEST_CORE_ON_SIGNAL)
- {
- struct sigaction sa; sa.sa_flags = 0;
- sigemptyset(&sa.sa_mask);
- sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL);
- sa.sa_handler=write_core;
- sigaction(SIGSEGV, &sa, NULL);
- }
-#endif
+ struct sigaction sa; sa.sa_flags = 0;
+ sigemptyset(&sa.sa_mask);
+ sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL);
+ sa.sa_handler=handle_segfault;
+ sigaction(SIGSEGV, &sa, NULL);
(void) sigemptyset(&set);
#ifdef THREAD_SPECIFIC_SIGPIPE
sigset(SIGPIPE,abort_thread);
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index eab67c835fd..ca33e9b2367 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -106,13 +106,13 @@ int generate_table(THD *thd, TABLE_LIST *table_list, TABLE *locked_table)
}
if (!error)
{
- send_ok(&thd->net); // This should return record count
mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
Query_log_event qinfo(thd, thd->query);
mysql_bin_log.write(&qinfo);
}
+ send_ok(&thd->net); // This should return record count
}
DBUG_RETURN(error ? -1 : 0);
}