140 lines
4.9 KiB
Diff
140 lines
4.9 KiB
Diff
|
mysql is not accounting for the "guard page" when setting thread stack size
|
||
|
requests. This is fatal on PPC systems, which may use guard pages as large
|
||
|
as 64K. This patch also documents the IA64 situation a bit better.
|
||
|
|
||
|
Note: there are quite a few other setstacksize calls besides the two in
|
||
|
mysqld.cc; is it important to fix any of the others?
|
||
|
|
||
|
Filed upstream at http://bugs.mysql.com/bug.php?id=35019
|
||
|
|
||
|
|
||
|
diff -up mysql-5.5.28/sql/mysqld.cc.p5 mysql-5.5.28/sql/mysqld.cc
|
||
|
--- mysql-5.5.28/sql/mysqld.cc.p5 2012-08-29 10:50:46.000000000 +0200
|
||
|
+++ mysql-5.5.28/sql/mysqld.cc 2012-12-06 14:13:59.765407494 +0100
|
||
|
@@ -2599,6 +2599,70 @@ static void init_signals(void)
|
||
|
}
|
||
|
|
||
|
|
||
|
+/* pthread_attr_setstacksize without so much platform-dependency */
|
||
|
+/* returns the actual stack size if possible */
|
||
|
+static size_t my_setstacksize(pthread_attr_t *attr, size_t stacksize)
|
||
|
+{
|
||
|
+ size_t guard_size = 0;
|
||
|
+
|
||
|
+#if defined(__ia64__) || defined(__ia64)
|
||
|
+ /*
|
||
|
+ On IA64, half of the requested stack size is used for "normal stack"
|
||
|
+ and half for "register stack". The space measured by check_stack_overrun
|
||
|
+ is the "normal stack", so double the request to make sure we have the
|
||
|
+ caller-expected amount of normal stack.
|
||
|
+
|
||
|
+ NOTE: there is no guarantee that the register stack can't grow faster
|
||
|
+ than normal stack, so it's very unclear that we won't dump core due to
|
||
|
+ stack overrun despite check_stack_overrun's efforts. Experimentation
|
||
|
+ shows that in the execution_constants test, the register stack grows
|
||
|
+ less than half as fast as normal stack, but perhaps other scenarios are
|
||
|
+ less forgiving. If it turns out that more space is needed for the
|
||
|
+ register stack, that could be forced (rather inefficiently) by using a
|
||
|
+ multiplier higher than 2 here.
|
||
|
+ */
|
||
|
+ stacksize *= 2;
|
||
|
+#endif
|
||
|
+
|
||
|
+ /*
|
||
|
+ On many machines, the "guard space" is subtracted from the requested
|
||
|
+ stack size, and that space is quite large on some platforms. So add
|
||
|
+ it to our request, if we can find out what it is.
|
||
|
+
|
||
|
+ FIXME: autoconfiscate use of pthread_attr_getguardsize
|
||
|
+ */
|
||
|
+ if (pthread_attr_getguardsize(attr, &guard_size))
|
||
|
+ guard_size = 0; /* if can't find it out, treat as 0 */
|
||
|
+
|
||
|
+ pthread_attr_setstacksize(attr, stacksize + guard_size);
|
||
|
+
|
||
|
+ /* Retrieve actual stack size if possible */
|
||
|
+#ifdef HAVE_PTHREAD_ATTR_GETSTACKSIZE
|
||
|
+ {
|
||
|
+ size_t real_stack_size= 0;
|
||
|
+ /* We must ignore real_stack_size = 0 as Solaris 2.9 can return 0 here */
|
||
|
+ if (pthread_attr_getstacksize(attr, &real_stack_size) == 0 &&
|
||
|
+ real_stack_size > guard_size)
|
||
|
+ {
|
||
|
+ real_stack_size -= guard_size;
|
||
|
+ if (real_stack_size < stacksize)
|
||
|
+ {
|
||
|
+ if (global_system_variables.log_warnings)
|
||
|
+ sql_print_warning("Asked for %ld thread stack, but got %ld",
|
||
|
+ (long) stacksize, (long) real_stack_size);
|
||
|
+ stacksize= real_stack_size;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
+#endif
|
||
|
+
|
||
|
+#if defined(__ia64__) || defined(__ia64)
|
||
|
+ stacksize /= 2;
|
||
|
+#endif
|
||
|
+ return stacksize;
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
static void start_signal_handler(void)
|
||
|
{
|
||
|
int error;
|
||
|
@@ -2609,15 +2673,7 @@ static void start_signal_handler(void)
|
||
|
#if !defined(HAVE_DEC_3_2_THREADS)
|
||
|
pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_SYSTEM);
|
||
|
(void) pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
|
||
|
-#if defined(__ia64__) || defined(__ia64)
|
||
|
- /*
|
||
|
- Peculiar things with ia64 platforms - it seems we only have half the
|
||
|
- stack size in reality, so we have to double it here
|
||
|
- */
|
||
|
- pthread_attr_setstacksize(&thr_attr,my_thread_stack_size*2);
|
||
|
-#else
|
||
|
- pthread_attr_setstacksize(&thr_attr,my_thread_stack_size);
|
||
|
-#endif
|
||
|
+ (void) my_setstacksize(&thr_attr,my_thread_stack_size);
|
||
|
#endif
|
||
|
|
||
|
mysql_mutex_lock(&LOCK_thread_count);
|
||
|
@@ -4398,36 +4454,8 @@ int mysqld_main(int argc, char **argv)
|
||
|
unireg_abort(1); // Will do exit
|
||
|
|
||
|
init_signals();
|
||
|
-#if defined(__ia64__) || defined(__ia64)
|
||
|
- /*
|
||
|
- Peculiar things with ia64 platforms - it seems we only have half the
|
||
|
- stack size in reality, so we have to double it here
|
||
|
- */
|
||
|
- pthread_attr_setstacksize(&connection_attrib,my_thread_stack_size*2);
|
||
|
-#else
|
||
|
- pthread_attr_setstacksize(&connection_attrib,my_thread_stack_size);
|
||
|
-#endif
|
||
|
#ifdef HAVE_PTHREAD_ATTR_GETSTACKSIZE
|
||
|
- {
|
||
|
- /* Retrieve used stack size; Needed for checking stack overflows */
|
||
|
- size_t stack_size= 0;
|
||
|
- pthread_attr_getstacksize(&connection_attrib, &stack_size);
|
||
|
-#if defined(__ia64__) || defined(__ia64)
|
||
|
- stack_size/= 2;
|
||
|
-#endif
|
||
|
- /* We must check if stack_size = 0 as Solaris 2.9 can return 0 here */
|
||
|
- if (stack_size && stack_size < my_thread_stack_size)
|
||
|
- {
|
||
|
- if (global_system_variables.log_warnings)
|
||
|
- sql_print_warning("Asked for %lu thread stack, but got %ld",
|
||
|
- my_thread_stack_size, (long) stack_size);
|
||
|
-#if defined(__ia64__) || defined(__ia64)
|
||
|
- my_thread_stack_size= stack_size*2;
|
||
|
-#else
|
||
|
- my_thread_stack_size= stack_size;
|
||
|
-#endif
|
||
|
- }
|
||
|
- }
|
||
|
+ my_thread_stack_size = my_setstacksize(&connection_attrib,my_thread_stack_size);
|
||
|
#endif
|
||
|
|
||
|
(void) thr_setconcurrency(concurrency); // 10 by default
|