Commit 6c76e5a0 authored by Vasil Dimov's avatar Vasil Dimov Committed by Marko Mäkelä

Fix Bug#24605956 SERVER MAY CRASH DUE TO A GLIBC BUG IN HANDLING SHORT-LIVED DETACHED THREADS

Avoid detaching and exiting from threads that may finish before the
caller has returned from pthread_create(). Only exit from such threads,
without detach and join with them later.

Patch submitted by: Laurynas Biveinis <laurynas.biveinis@gmail.com>
RB: 13983
Reviewed by: Sunny Bains <sunny.bains@oracle.com>
parent da76c1bd
...@@ -118,9 +118,19 @@ os_thread_create_func( ...@@ -118,9 +118,19 @@ os_thread_create_func(
os_thread_id_t* thread_id); /*!< out: id of the created os_thread_id_t* thread_id); /*!< out: id of the created
thread, or NULL */ thread, or NULL */
/** Exits the current thread. */ /** Waits until the specified thread completes and joins it.
Its return value is ignored.
@param[in,out] thread thread to join */
void void
os_thread_exit() os_thread_join(
os_thread_id_t thread);
/** Exits the current thread.
@param[in] detach if true, the thread will be detached right before
exiting. If false, another thread is responsible for joining this thread */
void
os_thread_exit(
bool detach = true)
UNIV_COLD MY_ATTRIBUTE((noreturn)); UNIV_COLD MY_ATTRIBUTE((noreturn));
/*****************************************************************//** /*****************************************************************//**
......
...@@ -161,9 +161,32 @@ os_thread_create_func( ...@@ -161,9 +161,32 @@ os_thread_create_func(
return((os_thread_t)new_thread_id); return((os_thread_t)new_thread_id);
} }
/** Exits the current thread. */ /** Waits until the specified thread completes and joins it.
Its return value is ignored.
@param[in,out] thread thread to join */
void void
os_thread_exit() os_thread_join(
os_thread_id_t thread)
{
#ifdef _WIN32
/* Do nothing. */
#else
#ifdef UNIV_DEBUG
const int ret =
#endif /* UNIV_DEBUG */
pthread_join(thread, NULL);
/* Waiting on already-quit threads is allowed. */
ut_ad(ret == 0 || ret == ESRCH);
#endif /* _WIN32 */
}
/** Exits the current thread.
@param[in] detach if true, the thread will be detached right before
exiting. If false, another thread is responsible for joining this thread */
void
os_thread_exit(
bool detach)
{ {
#ifdef UNIV_DEBUG_THREAD_CREATION #ifdef UNIV_DEBUG_THREAD_CREATION
ib::info() << "Thread exits, id " ib::info() << "Thread exits, id "
...@@ -184,7 +207,9 @@ os_thread_exit() ...@@ -184,7 +207,9 @@ os_thread_exit()
ExitThread(0); ExitThread(0);
#else #else
mutex_exit(&thread_mutex); mutex_exit(&thread_mutex);
if (detach) {
pthread_detach(pthread_self()); pthread_detach(pthread_self());
}
pthread_exit(NULL); pthread_exit(NULL);
#endif #endif
} }
......
...@@ -1144,7 +1144,7 @@ fts_parallel_merge( ...@@ -1144,7 +1144,7 @@ fts_parallel_merge(
os_event_set(psort_info->psort_common->merge_event); os_event_set(psort_info->psort_common->merge_event);
psort_info->child_status = FTS_CHILD_EXITING; psort_info->child_status = FTS_CHILD_EXITING;
os_thread_exit(); os_thread_exit(false);
OS_THREAD_DUMMY_RETURN; OS_THREAD_DUMMY_RETURN;
} }
...@@ -1157,15 +1157,16 @@ row_fts_start_parallel_merge( ...@@ -1157,15 +1157,16 @@ row_fts_start_parallel_merge(
fts_psort_t* merge_info) /*!< in: parallel sort info */ fts_psort_t* merge_info) /*!< in: parallel sort info */
{ {
int i = 0; int i = 0;
os_thread_id_t thd_id;
/* Kick off merge/insert threads */ /* Kick off merge/insert threads */
for (i = 0; i < FTS_NUM_AUX_INDEX; i++) { for (i = 0; i < FTS_NUM_AUX_INDEX; i++) {
merge_info[i].psort_id = i; merge_info[i].psort_id = i;
merge_info[i].child_status = 0; merge_info[i].child_status = 0;
merge_info[i].thread_hdl = os_thread_create(fts_parallel_merge, merge_info[i].thread_hdl = os_thread_create(
(void*) &merge_info[i], &thd_id); fts_parallel_merge,
(void*) &merge_info[i],
&merge_info[i].thread_hdl);
} }
} }
......
...@@ -4875,6 +4875,13 @@ row_merge_build_indexes( ...@@ -4875,6 +4875,13 @@ row_merge_build_indexes(
" threads exited when creating" " threads exited when creating"
" FTS index '" " FTS index '"
<< indexes[i]->name << "'"; << indexes[i]->name << "'";
} else {
for (j = 0; j < FTS_NUM_AUX_INDEX;
j++) {
os_thread_join(merge_info[j]
.thread_hdl);
}
} }
} else { } else {
/* This cannot report duplicates; an /* This cannot report duplicates; an
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment