In many places, the fact that a thread has terminated is signaled using condition
variable. Other threads wait on that condition and when it happens they assume
that the thread is gone while in fact some code in the thread is executed after
the condition was broadcast and before a call to pthread_exit(). This creates
several possible race conditions:
Issue 1: This is code from handle_slave_io() (slave.cc):
pthread_cond_broadcast(&mi->stop_cond); // tell the world we are done
my_thread_end();
pthread_exit(0);
The my_thread_end() function which frees local thread memory is called after
other threads potentially have assumed that this thread is dead. Under
unfavorable race conditions this can lead to memory allocation problems (like
double deallocation of the same memory.
RELATED BUG REPORTS: BUG#24486, BUG#24387?, ...?

Find all places in the code where a thread broadcasts the fact that it is
terminating. Move calls to my_thread_end() before the broadcast. In case thread
is restarted after a call to my_thread_end() make sure that my_thread_init() is
called again.
Places to look:
sql/slave.cc: handle_slave_{io,sql}()
sql/mysqld.cc: end_thread()
where else?