Here is one of the possible cases when "pending == false" and "ttp->thd == NULL" which triggers the assertion.
1. Two threads call "thd_timer_reset()" on the same object.
2. Thread 1 executes "status= my_os_timer_reset(&ttp->timer, &state);" and returns "status ==0" and "state == 1".
3. Thread 2 executes "status= my_os_timer_reset(&ttp->timer, &state);" and returns "status ==0" and "state == 1".
4. Thread 1 successfully acquires "ttp->mutex".
5. Thread 2 tries to acquire "ttp->mutex" and hangs.
6. Thread 1 executes "reap_timer()" with "pending == false" which returns "true". As a side effect "ttp->thd" is set to NULL.
7. Thread 1 sets "ttp->destroy" to "false"and releases "ttp->mutex".
8. Thread 2 finally acquires "ttp->mutex".
9. Thread 2 executes "reap_timer()" with "pending == false" and "ttp->thd == NULL".
10. The "DBUG_ASSERT(pending || ttp->thd);" assertion is triggered in Thread 2.
Unable to reproduce on 5.6 (commit ee0f346).
However a race condition is theoretically possible.
Consider the following function "thd_timer_reset()" that calls "reap_timer()"
thd_timer_t * thd_timer_ reset(thd_ timer_t *ttp) ENTER(" thd_timer_ reset") ;
{
bool unreachable;
int status, state;
DBUG_
status= my_os_timer_ reset(& ttp->timer, &state);
pthread_ mutex_lock( &ttp->mutex) ; mutex_unlock( &ttp->mutex) ;
unreachable= reap_timer(ttp, status ? true : !state);
ttp->destroy= unreachable ? false : true;
pthread_
DBUG_ RETURN( unreachable ? ttp : NULL);
}
static bool reap_timer( thd_timer_ t *ttp, bool pending)
{
bool unreachable;
DBUG_ ASSERT( !ttp->destroy) ;
DBUG_ ASSERT( pending || ttp->thd);
unreachable= pending ? ttp->thd == NULL : true;
ttp->thd= NULL;
return unreachable;
}
Here is one of the possible cases when "pending == false" and "ttp->thd == NULL" which triggers the assertion. reset(& ttp->timer, &state);" and returns "status ==0" and "state == 1". reset(& ttp->timer, &state);" and returns "status ==0" and "state == 1". pending || ttp->thd);" assertion is triggered in Thread 2.
1. Two threads call "thd_timer_reset()" on the same object.
2. Thread 1 executes "status= my_os_timer_
3. Thread 2 executes "status= my_os_timer_
4. Thread 1 successfully acquires "ttp->mutex".
5. Thread 2 tries to acquire "ttp->mutex" and hangs.
6. Thread 1 executes "reap_timer()" with "pending == false" which returns "true". As a side effect "ttp->thd" is set to NULL.
7. Thread 1 sets "ttp->destroy" to "false"and releases "ttp->mutex".
8. Thread 2 finally acquires "ttp->mutex".
9. Thread 2 executes "reap_timer()" with "pending == false" and "ttp->thd == NULL".
10. The "DBUG_ASSERT(