|
| 1 | +mysql is not accounting for the "guard page" when setting thread stack size |
| 2 | +requests. This is fatal on PPC systems, which may use guard pages as large |
| 3 | +as 64K. This patch also documents the IA64 situation a bit better. |
| 4 | + |
| 5 | +Note: there are quite a few other setstacksize calls besides the two in |
| 6 | +mysqld.cc; is it important to fix any of the others? |
| 7 | + |
| 8 | +Filed upstream at http://bugs.mysql.com/bug.php?id=35019 |
| 9 | + |
| 10 | + |
| 11 | +diff -Naur mysql-5.1.30.orig/sql/mysqld.cc mysql-5.1.30/sql/mysqld.cc |
| 12 | +--- mysql-5.1.30.orig/sql/mysqld.cc 2008-11-14 11:37:13.000000000 -0500 |
| 13 | ++++ mysql-5.1.30/sql/mysqld.cc 2009-01-13 12:08:35.000000000 -0500 |
| 14 | +@@ -2653,6 +2653,70 @@ |
| 15 | + } |
| 16 | + |
| 17 | + |
| 18 | ++/* pthread_attr_setstacksize without so much platform-dependency */ |
| 19 | ++/* returns the actual stack size if possible */ |
| 20 | ++static size_t my_setstacksize(pthread_attr_t *attr, size_t stacksize) |
| 21 | ++{ |
| 22 | ++ size_t guard_size = 0; |
| 23 | ++ |
| 24 | ++#if defined(__ia64__) || defined(__ia64) |
| 25 | ++ /* |
| 26 | ++ On IA64, half of the requested stack size is used for "normal stack" |
| 27 | ++ and half for "register stack". The space measured by check_stack_overrun |
| 28 | ++ is the "normal stack", so double the request to make sure we have the |
| 29 | ++ caller-expected amount of normal stack. |
| 30 | ++ |
| 31 | ++ NOTE: there is no guarantee that the register stack can't grow faster |
| 32 | ++ than normal stack, so it's very unclear that we won't dump core due to |
| 33 | ++ stack overrun despite check_stack_overrun's efforts. Experimentation |
| 34 | ++ shows that in the execution_constants test, the register stack grows |
| 35 | ++ less than half as fast as normal stack, but perhaps other scenarios are |
| 36 | ++ less forgiving. If it turns out that more space is needed for the |
| 37 | ++ register stack, that could be forced (rather inefficiently) by using a |
| 38 | ++ multiplier higher than 2 here. |
| 39 | ++ */ |
| 40 | ++ stacksize *= 2; |
| 41 | ++#endif |
| 42 | ++ |
| 43 | ++ /* |
| 44 | ++ On many machines, the "guard space" is subtracted from the requested |
| 45 | ++ stack size, and that space is quite large on some platforms. So add |
| 46 | ++ it to our request, if we can find out what it is. |
| 47 | ++ |
| 48 | ++ FIXME: autoconfiscate use of pthread_attr_getguardsize |
| 49 | ++ */ |
| 50 | ++ if (pthread_attr_getguardsize(attr, &guard_size)) |
| 51 | ++ guard_size = 0; /* if can't find it out, treat as 0 */ |
| 52 | ++ |
| 53 | ++ pthread_attr_setstacksize(attr, stacksize + guard_size); |
| 54 | ++ |
| 55 | ++ /* Retrieve actual stack size if possible */ |
| 56 | ++#ifdef HAVE_PTHREAD_ATTR_GETSTACKSIZE |
| 57 | ++ { |
| 58 | ++ size_t real_stack_size= 0; |
| 59 | ++ /* We must ignore real_stack_size = 0 as Solaris 2.9 can return 0 here */ |
| 60 | ++ if (pthread_attr_getstacksize(attr, &real_stack_size) == 0 && |
| 61 | ++ real_stack_size > guard_size) |
| 62 | ++ { |
| 63 | ++ real_stack_size -= guard_size; |
| 64 | ++ if (real_stack_size < stacksize) |
| 65 | ++ { |
| 66 | ++ if (global_system_variables.log_warnings) |
| 67 | ++ sql_print_warning("Asked for %ld thread stack, but got %ld", |
| 68 | ++ (long) stacksize, (long) real_stack_size); |
| 69 | ++ stacksize= real_stack_size; |
| 70 | ++ } |
| 71 | ++ } |
| 72 | ++ } |
| 73 | ++#endif |
| 74 | ++ |
| 75 | ++#if defined(__ia64__) || defined(__ia64) |
| 76 | ++ stacksize /= 2; |
| 77 | ++#endif |
| 78 | ++ return stacksize; |
| 79 | ++} |
| 80 | ++ |
| 81 | ++ |
| 82 | + static void start_signal_handler(void) |
| 83 | + { |
| 84 | + int error; |
| 85 | +@@ -2663,15 +2727,7 @@ |
| 86 | + #if !defined(HAVE_DEC_3_2_THREADS) |
| 87 | + pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_SYSTEM); |
| 88 | + (void) pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED); |
| 89 | +-#if defined(__ia64__) || defined(__ia64) |
| 90 | +- /* |
| 91 | +- Peculiar things with ia64 platforms - it seems we only have half the |
| 92 | +- stack size in reality, so we have to double it here |
| 93 | +- */ |
| 94 | +- pthread_attr_setstacksize(&thr_attr,my_thread_stack_size*2); |
| 95 | +-#else |
| 96 | +- pthread_attr_setstacksize(&thr_attr,my_thread_stack_size); |
| 97 | +-#endif |
| 98 | ++ (void) my_setstacksize(&thr_attr,my_thread_stack_size); |
| 99 | + #endif |
| 100 | + |
| 101 | + mysql_mutex_lock(&LOCK_thread_count); |
| 102 | +@@ -4445,37 +4501,7 @@ |
| 103 | + unireg_abort(1); // Will do exit |
| 104 | + |
| 105 | + init_signals(); |
| 106 | +-#if defined(__ia64__) || defined(__ia64) |
| 107 | +- /* |
| 108 | +- Peculiar things with ia64 platforms - it seems we only have half the |
| 109 | +- stack size in reality, so we have to double it here |
| 110 | +- */ |
| 111 | +- pthread_attr_setstacksize(&connection_attrib,my_thread_stack_size*2); |
| 112 | +-#else |
| 113 | +- pthread_attr_setstacksize(&connection_attrib,my_thread_stack_size); |
| 114 | +-#endif |
| 115 | +-#ifdef HAVE_PTHREAD_ATTR_GETSTACKSIZE |
| 116 | +- { |
| 117 | +- /* Retrieve used stack size; Needed for checking stack overflows */ |
| 118 | +- size_t stack_size= 0; |
| 119 | +- pthread_attr_getstacksize(&connection_attrib, &stack_size); |
| 120 | +-#if defined(__ia64__) || defined(__ia64) |
| 121 | +- stack_size/= 2; |
| 122 | +-#endif |
| 123 | +- /* We must check if stack_size = 0 as Solaris 2.9 can return 0 here */ |
| 124 | +- if (stack_size && stack_size < my_thread_stack_size) |
| 125 | +- { |
| 126 | +- if (global_system_variables.log_warnings) |
| 127 | +- sql_print_warning("Asked for %lu thread stack, but got %ld", |
| 128 | +- my_thread_stack_size, (long) stack_size); |
| 129 | +-#if defined(__ia64__) || defined(__ia64) |
| 130 | +- my_thread_stack_size= stack_size*2; |
| 131 | +-#else |
| 132 | +- my_thread_stack_size= stack_size; |
| 133 | +-#endif |
| 134 | +- } |
| 135 | +- } |
| 136 | +-#endif |
| 137 | ++ my_thread_stack_size = my_setstacksize(&connection_attrib,my_thread_stack_size); |
| 138 | + |
| 139 | + (void) thr_setconcurrency(concurrency); // 10 by default |
| 140 | + |
0 commit comments