summaryrefslogtreecommitdiff
path: root/mysys/waiting_threads.c
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mysql.com>2009-01-07 21:50:11 +0100
committerSergei Golubchik <serg@mysql.com>2009-01-07 21:50:11 +0100
commitc45bf1b3cc1dd241f26210ebdef836566124bef0 (patch)
tree343c28d020fc11314ada366229eeff31e49ccd29 /mysys/waiting_threads.c
parent6aa97fb6648e08745533eacdf5e77afd882c3246 (diff)
downloadmariadb-git-c45bf1b3cc1dd241f26210ebdef836566124bef0.tar.gz
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
Diffstat (limited to 'mysys/waiting_threads.c')
-rw-r--r--mysys/waiting_threads.c22
1 files changed, 21 insertions, 1 deletions
diff --git a/mysys/waiting_threads.c b/mysys/waiting_threads.c
index 14b1d639d00..f2dff238b46 100644
--- a/mysys/waiting_threads.c
+++ b/mysys/waiting_threads.c
@@ -613,7 +613,24 @@ static int deadlock(WT_THD *thd, WT_THD *blocker, uint depth,
if (ret == WT_DEADLOCK && depth)
change_victim(blocker, &arg);
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);
+ }
/* notify the victim, if appropriate */
if (ret == WT_DEADLOCK && arg.victim != thd)
{
@@ -888,7 +905,10 @@ int wt_thd_cond_timedwait(WT_THD *thd, pthread_mutex_t *mutex)
ret= pthread_cond_timedwait(&rc->cond, mutex, &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;
else if (*thd->timeout_long > *thd->timeout_short)
{