Commit c45bf1b3 authored by Sergei Golubchik's avatar Sergei Golubchik

Bug#40990 Maria: failure of maria.test & maria_notemebedded in deadlock detection

detect a case when a blocker has removed itself and signalled after the condition timed out
but before it (cond_wait) acquired the mutex back
parent 6aa97fb6
...@@ -185,6 +185,7 @@ typedef struct st_wt_thd { ...@@ -185,6 +185,7 @@ typedef struct st_wt_thd {
#define WT_OK 0 #define WT_OK 0
#define WT_DEADLOCK -1 #define WT_DEADLOCK -1
#define WT_DEPTH_EXCEEDED -2 #define WT_DEPTH_EXCEEDED -2
#define WT_FREE_TO_GO -3
void wt_init(void); void wt_init(void);
void wt_end(void); void wt_end(void);
......
...@@ -613,7 +613,24 @@ static int deadlock(WT_THD *thd, WT_THD *blocker, uint depth, ...@@ -613,7 +613,24 @@ static int deadlock(WT_THD *thd, WT_THD *blocker, uint depth,
if (ret == WT_DEADLOCK && depth) if (ret == WT_DEADLOCK && depth)
change_victim(blocker, &arg); change_victim(blocker, &arg);
if (arg.rc) if (arg.rc)
{
/*
Special return code if there's nobody to wait for.
depth == 0 means that we start the search from thd (thd == blocker).
ret == WT_OK means that no cycle was found and arg.rc == thd->waiting_for.
and arg.rc->owners.elements == 0 means that (applying the rule above)
thd->waiting_for->owners.elements == 0, and thd doesn't have anybody to
wait for.
*/
if (depth == 0 && ret == WT_OK && arg.rc->owners.elements == 0)
{
DBUG_ASSERT(thd == blocker);
DBUG_ASSERT(arg.rc == thd->waiting_for);
ret= WT_FREE_TO_GO;
}
rc_unlock(arg.rc); rc_unlock(arg.rc);
}
/* notify the victim, if appropriate */ /* notify the victim, if appropriate */
if (ret == WT_DEADLOCK && arg.victim != thd) if (ret == WT_DEADLOCK && arg.victim != thd)
{ {
...@@ -888,7 +905,10 @@ int wt_thd_cond_timedwait(WT_THD *thd, pthread_mutex_t *mutex) ...@@ -888,7 +905,10 @@ int wt_thd_cond_timedwait(WT_THD *thd, pthread_mutex_t *mutex)
ret= pthread_cond_timedwait(&rc->cond, mutex, &timeout); ret= pthread_cond_timedwait(&rc->cond, mutex, &timeout);
if (ret == WT_TIMEOUT) if (ret == WT_TIMEOUT)
{ {
if (deadlock(thd, thd, 0, *thd->deadlock_search_depth_long)) int r= deadlock(thd, thd, 0, *thd->deadlock_search_depth_long);
if (r == WT_FREE_TO_GO)
ret= WT_OK;
else if (r != WT_OK)
ret= WT_DEADLOCK; ret= WT_DEADLOCK;
else if (*thd->timeout_long > *thd->timeout_short) else if (*thd->timeout_long > *thd->timeout_short)
{ {
......
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