Commit 06a0882d authored by Marko Mäkelä's avatar Marko Mäkelä

Bug#48197: Concurrent rw_lock_free may cause assertion failure

rw_lock_t: Remove magic_n unless UNIV_DEBUG is defined.
rw_lock_free(): Invalidate magic_n only after removing from rw_lock_list.
parent 831e6d93
...@@ -555,11 +555,12 @@ struct rw_lock_struct { ...@@ -555,11 +555,12 @@ struct rw_lock_struct {
unsigned cline:14; /*!< Line where created */ unsigned cline:14; /*!< Line where created */
unsigned last_s_line:14; /*!< Line number where last time s-locked */ unsigned last_s_line:14; /*!< Line number where last time s-locked */
unsigned last_x_line:14; /*!< Line number where last time x-locked */ unsigned last_x_line:14; /*!< Line number where last time x-locked */
#ifdef UNIV_DEBUG
ulint magic_n; /*!< RW_LOCK_MAGIC_N */ ulint magic_n; /*!< RW_LOCK_MAGIC_N */
};
/** Value of rw_lock_struct::magic_n */ /** Value of rw_lock_struct::magic_n */
#define RW_LOCK_MAGIC_N 22643 #define RW_LOCK_MAGIC_N 22643
#endif /* UNIV_DEBUG */
};
#ifdef UNIV_SYNC_DEBUG #ifdef UNIV_SYNC_DEBUG
/** The structure for storing debug info of an rw-lock */ /** The structure for storing debug info of an rw-lock */
......
...@@ -267,7 +267,7 @@ rw_lock_create_func( ...@@ -267,7 +267,7 @@ rw_lock_create_func(
lock->level = level; lock->level = level;
#endif /* UNIV_SYNC_DEBUG */ #endif /* UNIV_SYNC_DEBUG */
lock->magic_n = RW_LOCK_MAGIC_N; ut_d(lock->magic_n = RW_LOCK_MAGIC_N);
lock->cfile_name = cfile_name; lock->cfile_name = cfile_name;
lock->cline = (unsigned int) cline; lock->cline = (unsigned int) cline;
...@@ -282,10 +282,8 @@ rw_lock_create_func( ...@@ -282,10 +282,8 @@ rw_lock_create_func(
mutex_enter(&rw_lock_list_mutex); mutex_enter(&rw_lock_list_mutex);
if (UT_LIST_GET_LEN(rw_lock_list) > 0) { ut_ad(UT_LIST_GET_FIRST(rw_lock_list) == NULL
ut_a(UT_LIST_GET_FIRST(rw_lock_list)->magic_n || UT_LIST_GET_FIRST(rw_lock_list)->magic_n == RW_LOCK_MAGIC_N);
== RW_LOCK_MAGIC_N);
}
UT_LIST_ADD_FIRST(list, rw_lock_list, lock); UT_LIST_ADD_FIRST(list, rw_lock_list, lock);
...@@ -305,8 +303,6 @@ rw_lock_free( ...@@ -305,8 +303,6 @@ rw_lock_free(
ut_ad(rw_lock_validate(lock)); ut_ad(rw_lock_validate(lock));
ut_a(lock->lock_word == X_LOCK_DECR); ut_a(lock->lock_word == X_LOCK_DECR);
lock->magic_n = 0;
#ifndef INNODB_RW_LOCKS_USE_ATOMICS #ifndef INNODB_RW_LOCKS_USE_ATOMICS
mutex_free(rw_lock_get_mutex(lock)); mutex_free(rw_lock_get_mutex(lock));
#endif /* INNODB_RW_LOCKS_USE_ATOMICS */ #endif /* INNODB_RW_LOCKS_USE_ATOMICS */
...@@ -316,16 +312,16 @@ rw_lock_free( ...@@ -316,16 +312,16 @@ rw_lock_free(
os_event_free(lock->wait_ex_event); os_event_free(lock->wait_ex_event);
if (UT_LIST_GET_PREV(list, lock)) { ut_ad(UT_LIST_GET_PREV(list, lock) == NULL
ut_a(UT_LIST_GET_PREV(list, lock)->magic_n == RW_LOCK_MAGIC_N); || UT_LIST_GET_PREV(list, lock)->magic_n == RW_LOCK_MAGIC_N);
} ut_ad(UT_LIST_GET_NEXT(list, lock) == NULL
if (UT_LIST_GET_NEXT(list, lock)) { || UT_LIST_GET_NEXT(list, lock)->magic_n == RW_LOCK_MAGIC_N);
ut_a(UT_LIST_GET_NEXT(list, lock)->magic_n == RW_LOCK_MAGIC_N);
}
UT_LIST_REMOVE(list, rw_lock_list, lock); UT_LIST_REMOVE(list, rw_lock_list, lock);
mutex_exit(&rw_lock_list_mutex); mutex_exit(&rw_lock_list_mutex);
ut_d(lock->magic_n = 0);
} }
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
...@@ -344,7 +340,7 @@ rw_lock_validate( ...@@ -344,7 +340,7 @@ rw_lock_validate(
ulint waiters = rw_lock_get_waiters(lock); ulint waiters = rw_lock_get_waiters(lock);
lint lock_word = lock->lock_word; lint lock_word = lock->lock_word;
ut_a(lock->magic_n == RW_LOCK_MAGIC_N); ut_ad(lock->magic_n == RW_LOCK_MAGIC_N);
ut_a(waiters == 0 || waiters == 1); ut_a(waiters == 0 || waiters == 1);
ut_a(lock_word > -X_LOCK_DECR ||(-lock_word) % X_LOCK_DECR == 0); ut_a(lock_word > -X_LOCK_DECR ||(-lock_word) % X_LOCK_DECR == 0);
......
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