Merge lp:~vlad-lesin/percona-server/5.6-bug-1351148 into lp:percona-server/5.6

Proposed by Vlad Lesin
Status: Merged
Approved by: Laurynas Biveinis
Approved revision: no longer in the source branch.
Merged at revision: 705
Proposed branch: lp:~vlad-lesin/percona-server/5.6-bug-1351148
Merge into: lp:percona-server/5.6
Diff against target: 69 lines (+38/-3)
2 files modified
mysys/lf_alloc-pin.c (+10/-1)
mysys/my_thr_init.c (+28/-2)
To merge this branch: bzr merge lp:~vlad-lesin/percona-server/5.6-bug-1351148
Reviewer Review Type Date Requested Status
Laurynas Biveinis (community) Approve
Registry Administrators Pending
Review via email: mp+235721@code.launchpad.net

Description of the change

Bug #1351128 fix.

  The bug's summary:

  1) The value in pins->stack_ends_here is actually incorrect. This value is
  calculated when the thread is initialized in my_thread_init(). The problem is
  that the value doesn't take into account existing stack usage and just adds the
  thread stack size to calculate the beginning of the stack.

  2) _lf_pinbox_real_free() is using alloca() in a very unsafe way. alloca()
  should only be used by leaf functions, since you cannot predict the amount of
  stack space that non-leaf functions will use. As pins->stack_ends_here is
  calculated in wrong way and there is no window for the qsort() which is invoked
  from _lf_pinbox_real_free() after alloca(), stack overflow can take place.

  The solution:

  1) Take into accout the current stack offset when stack size is calculated
  in my_thread_init();

  2) Don't allocate the whole free stack space in _lf_pinbox_real_free(),
  take some window for qsort();

http://jenkins.percona.com/view/PS%205.6/job/percona-server-5.6-param/714/

To post a comment you must log in.
Revision history for this message
Laurynas Biveinis (laurynas-biveinis) :
review: Needs Fixing
Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote :

5.6 not merged from the last 5.5 push?

review: Needs Fixing
Revision history for this message
Vlad Lesin (vlad-lesin) wrote :

> 5.6 not merged from the last 5.5 push?

It looks like I forgot to push the last version. Have just pushed.

Revision history for this message
Laurynas Biveinis (laurynas-biveinis) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'mysys/lf_alloc-pin.c'
--- mysys/lf_alloc-pin.c 2014-12-01 07:53:48 +0000
+++ mysys/lf_alloc-pin.c 2014-12-02 14:03:08 +0000
@@ -105,6 +105,13 @@
105105
106#define LF_PINBOX_MAX_PINS 65536106#define LF_PINBOX_MAX_PINS 65536
107107
108/*
109 When allocation on stack happens leave this
110 amount of stack memory for further functions
111 call.
112*/
113#define LF_PINBOX_EXTRA_STACK_SPACE 8192
114
108static void _lf_pinbox_real_free(LF_PINS *pins);115static void _lf_pinbox_real_free(LF_PINS *pins);
109116
110/*117/*
@@ -349,7 +356,9 @@
349 {356 {
350 int alloca_size= sizeof(void *)*LF_PINBOX_PINS*npins;357 int alloca_size= sizeof(void *)*LF_PINBOX_PINS*npins;
351 /* create a sorted list of pinned addresses, to speed up searches */358 /* create a sorted list of pinned addresses, to speed up searches */
352 if (available_stack_size(&pinbox, *pins->stack_ends_here) > alloca_size)359 if (available_stack_size(&pinbox, *pins->stack_ends_here) >
360 /* leave LF_PINBOX_EXTRA_STACK_SPACE bytes for qsort() call */
361 (alloca_size + LF_PINBOX_EXTRA_STACK_SPACE))
353 {362 {
354 struct st_harvester hv;363 struct st_harvester hv;
355 addr= (void **) alloca(alloca_size);364 addr= (void **) alloca(alloca_size);
356365
=== modified file 'mysys/my_thr_init.c'
--- mysys/my_thr_init.c 2014-12-01 07:53:48 +0000
+++ mysys/my_thr_init.c 2014-12-02 14:03:08 +0000
@@ -297,8 +297,34 @@
297 mysql_mutex_init(key_my_thread_var_mutex, &tmp->mutex, MY_MUTEX_INIT_FAST);297 mysql_mutex_init(key_my_thread_var_mutex, &tmp->mutex, MY_MUTEX_INIT_FAST);
298 mysql_cond_init(key_my_thread_var_suspend, &tmp->suspend, NULL);298 mysql_cond_init(key_my_thread_var_suspend, &tmp->suspend, NULL);
299299
300 tmp->stack_ends_here= (char*)&tmp +300#if defined(_GNU_SOURCE) && (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600)
301 STACK_DIRECTION * (long)my_thread_stack_size;301 {
302 pthread_attr_t attr;
303 char* stack_addr;
304 size_t stack_size;
305
306 if (pthread_attr_init(&attr) ||
307 pthread_getattr_np(tmp->pthread_self, &attr) ||
308 pthread_attr_getstack(&attr, (void**)&stack_addr, &stack_size))
309 {
310 error= 1;
311 goto end;
312 }
313 tmp->stack_ends_here= stack_addr;
314
315 if (pthread_attr_destroy(&attr))
316 {
317 error= 1;
318 goto end;
319 }
320 }
321#else //defined(_GNU_SOURCE) && (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600)
322 /* assuming tmp is located within the first page of the stack */
323 tmp->stack_ends_here= (void **)(((long long)&tmp & (~((long long)my_getpagesize() - 1))) +
324 ((STACK_DIRECTION == 1) ?
325 my_thread_stack_size :
326 my_getpagesize() - my_thread_stack_size));
327#endif //defined(_GNU_SOURCE) && (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600)
302328
303 mysql_mutex_lock(&THR_LOCK_threads);329 mysql_mutex_lock(&THR_LOCK_threads);
304 tmp->id= ++thread_id;330 tmp->id= ++thread_id;

Subscribers

People subscribed via source and target branches