From 53382ac128d9571b5f779bf625567fc3ea0b475e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Fri, 1 May 2015 14:23:08 +0300 Subject: [PATCH] MDEV-8079: Crash when running MariaDB Debug with InnoDB on Windows Problem was that std::vector was allocated using calloc instead of new, this caused vector constructor not being called and vector metadata not initialized. --- storage/innobase/sync/sync0sync.cc | 60 ++++++++---------------------- storage/xtradb/sync/sync0sync.cc | 60 ++++++++---------------------- 2 files changed, 32 insertions(+), 88 deletions(-) diff --git a/storage/innobase/sync/sync0sync.cc b/storage/innobase/sync/sync0sync.cc index 4176fc8eec9..0552c147adf 100644 --- a/storage/innobase/sync/sync0sync.cc +++ b/storage/innobase/sync/sync0sync.cc @@ -49,27 +49,6 @@ Created 9/5/1995 Heikki Tuuri #include -/* There is a bug in Visual Studio 2010. -Visual Studio has a feature "Checked Iterators". In a debug build, every -iterator operation is checked at runtime for errors, e.g., out of range. -Because of bug there is runtime error on following code -for (std::vector::iterator it = array->elems.begin(); it != -array->elems.end(); ++it) and runtime check fails on comparison -it != array->elems.end() that is correct and standard way to do end -of range comparison. -Disable this "Checked Iterators" for Windows and Debug if defined. -*/ -#ifdef UNIV_DEBUG -#ifdef __WIN__ -#ifdef _ITERATOR_DEBUG_LEVEL -#undef _ITERATOR_DEBUG_LEVEL -#define _ITERATOR_DEBUG_LEVEL 0 -#endif /* _ITERATOR_DEBUG_LEVEL */ -#endif /* __WIN__*/ -#endif /* UNIV_DEBUG */ - -#include - /* REASONS FOR IMPLEMENTING THE SPIN LOCK MUTEX ============================================ @@ -247,11 +226,8 @@ UNIV_INTERN ibool sync_order_checks_on = FALSE; static const ulint SYNC_THREAD_N_LEVELS = 10000; /** Array for tracking sync levels per thread. */ -struct sync_arr_t { - ulint n_elems; /*!< Number of elements in the array */ +typedef std::vector sync_arr_t; - std::vector elems; /*!< Vector of elements */ -}; /** Mutexes or rw-locks held by a thread */ struct sync_thread_t{ @@ -879,10 +855,10 @@ sync_thread_levels_g( { ulint i; - for (i = 0; i < arr->n_elems; i++) { + for (i = 0; i < arr->size(); i++) { const sync_level_t* slot; - slot = &arr->elems[i]; + slot = (const sync_level_t*)&(arr->at(i)); if (slot->latch != NULL && slot->level <= limit) { if (warn) { @@ -914,10 +890,10 @@ sync_thread_levels_contain( { ulint i; - for (i = 0; i < arr->n_elems; i++) { + for (i = 0; i < arr->size(); i++) { const sync_level_t* slot; - slot = &arr->elems[i]; + slot = (const sync_level_t*)&(arr->at(i)); if (slot->latch != NULL && slot->level == level) { @@ -961,10 +937,10 @@ sync_thread_levels_contains( arr = thread_slot->levels; - for (i = 0; i < arr->n_elems; i++) { + for (i = 0; i < arr->size(); i++) { sync_level_t* slot; - slot = &arr->elems[i]; + slot = (sync_level_t*)&(arr->at(i)); if (slot->latch != NULL && slot->level == level) { @@ -1010,10 +986,10 @@ sync_thread_levels_nonempty_gen( arr = thread_slot->levels; - for (i = 0; i < arr->n_elems; ++i) { + for (i = 0; i < arr->size(); ++i) { const sync_level_t* slot; - slot = &arr->elems[i]; + slot = (const sync_level_t*)&(arr->at(i)); if (slot->latch != NULL && (!dict_mutex_allowed @@ -1070,10 +1046,10 @@ sync_thread_levels_nonempty_trx( arr = thread_slot->levels; - for (i = 0; i < arr->n_elems; ++i) { + for (i = 0; i < arr->size(); ++i) { const sync_level_t* slot; - slot = &arr->elems[i]; + slot = (const sync_level_t*)&(arr->at(i)); if (slot->latch != NULL && (!has_search_latch @@ -1133,7 +1109,7 @@ sync_thread_add_level( if (thread_slot == NULL) { /* We have to allocate the level array for a new thread */ - array = static_cast(calloc(1, sizeof(sync_arr_t))); + array = new sync_arr_t(); ut_a(array != NULL); thread_slot = sync_thread_level_arrays_find_free(); thread_slot->levels = array; @@ -1347,10 +1323,9 @@ sync_thread_add_level( levels_ok: - array->n_elems++; sync_level.latch = latch; sync_level.level = level; - array->elems.push_back(sync_level); + array->push_back(sync_level); mutex_exit(&sync_thread_mutex); } @@ -1396,15 +1371,14 @@ sync_thread_reset_level( array = thread_slot->levels; - for (std::vector::iterator it = array->elems.begin(); it != array->elems.end(); ++it) { + for (std::vector::iterator it = array->begin(); it != array->end(); ++it) { sync_level_t level = *it; if (level.latch != latch) { continue; } - array->elems.erase(it); - array->n_elems--; + array->erase(it); mutex_exit(&sync_thread_mutex); return(TRUE); } @@ -1491,9 +1465,7 @@ sync_thread_level_arrays_free(void) /* If this slot was allocated then free the slot memory too. */ if (slot->levels != NULL) { - slot->levels->elems.erase(slot->levels->elems.begin(),slot->levels->elems.end()); - free(slot->levels); - slot->levels = NULL; + delete slot->levels; } } diff --git a/storage/xtradb/sync/sync0sync.cc b/storage/xtradb/sync/sync0sync.cc index 60b836fb720..dabf70fd041 100644 --- a/storage/xtradb/sync/sync0sync.cc +++ b/storage/xtradb/sync/sync0sync.cc @@ -50,27 +50,6 @@ Created 9/5/1995 Heikki Tuuri #include -/* There is a bug in Visual Studio 2010. -Visual Studio has a feature "Checked Iterators". In a debug build, every -iterator operation is checked at runtime for errors, e.g., out of range. -Because of bug there is runtime error on following code -for (std::vector::iterator it = array->elems.begin(); it != -array->elems.end(); ++it) and runtime check fails on comparison -it != array->elems.end() that is correct and standard way to do end -of range comparison. -Disable this "Checked Iterators" for Windows and Debug if defined. -*/ -#ifdef UNIV_DEBUG -#ifdef __WIN__ -#ifdef _ITERATOR_DEBUG_LEVEL -#undef _ITERATOR_DEBUG_LEVEL -#define _ITERATOR_DEBUG_LEVEL 0 -#endif /* _ITERATOR_DEBUG_LEVEL */ -#endif /* __WIN__*/ -#endif /* UNIV_DEBUG */ - -#include - /* REASONS FOR IMPLEMENTING THE SPIN LOCK MUTEX ============================================ @@ -251,11 +230,8 @@ UNIV_INTERN ibool sync_order_checks_on = FALSE; static const ulint SYNC_THREAD_N_LEVELS = 10000; /** Array for tracking sync levels per thread. */ -struct sync_arr_t { - ulint n_elems; /*!< Number of elements in the array */ +typedef std::vector sync_arr_t; - std::vector elems; /*!< Vector of elements */ -}; /** Mutexes or rw-locks held by a thread */ struct sync_thread_t{ @@ -982,10 +958,10 @@ sync_thread_levels_g( { ulint i; - for (i = 0; i < arr->n_elems; i++) { + for (i = 0; i < arr->size(); i++) { const sync_level_t* slot; - slot = &arr->elems[i]; + slot = (const sync_level_t*)&(arr->at(i)); if (slot->latch != NULL && slot->level <= limit) { if (warn) { @@ -1017,10 +993,10 @@ sync_thread_levels_contain( { ulint i; - for (i = 0; i < arr->n_elems; i++) { + for (i = 0; i < arr->size(); i++) { const sync_level_t* slot; - slot = &arr->elems[i]; + slot = (const sync_level_t*)&(arr->at(i)); if (slot->latch != NULL && slot->level == level) { @@ -1064,10 +1040,10 @@ sync_thread_levels_contains( arr = thread_slot->levels; - for (i = 0; i < arr->n_elems; i++) { + for (i = 0; i < arr->size(); i++) { sync_level_t* slot; - slot = &arr->elems[i]; + slot = (sync_level_t*)&(arr->at(i)); if (slot->latch != NULL && slot->level == level) { @@ -1113,10 +1089,10 @@ sync_thread_levels_nonempty_gen( arr = thread_slot->levels; - for (i = 0; i < arr->n_elems; ++i) { + for (i = 0; i < arr->size(); ++i) { const sync_level_t* slot; - slot = &arr->elems[i]; + slot = (const sync_level_t*)&(arr->at(i)); if (slot->latch != NULL && (!dict_mutex_allowed @@ -1173,10 +1149,10 @@ sync_thread_levels_nonempty_trx( arr = thread_slot->levels; - for (i = 0; i < arr->n_elems; ++i) { + for (i = 0; i < arr->size(); ++i) { const sync_level_t* slot; - slot = &arr->elems[i]; + slot = (const sync_level_t*)&(arr->at(i)); if (slot->latch != NULL && (!has_search_latch @@ -1236,7 +1212,7 @@ sync_thread_add_level( if (thread_slot == NULL) { /* We have to allocate the level array for a new thread */ - array = static_cast(calloc(1, sizeof(sync_arr_t))); + array = new sync_arr_t(); ut_a(array != NULL); thread_slot = sync_thread_level_arrays_find_free(); thread_slot->levels = array; @@ -1467,10 +1443,9 @@ sync_thread_add_level( levels_ok: - array->n_elems++; sync_level.latch = latch; sync_level.level = level; - array->elems.push_back(sync_level); + array->push_back(sync_level); mutex_exit(&sync_thread_mutex); } @@ -1516,15 +1491,14 @@ sync_thread_reset_level( array = thread_slot->levels; - for (std::vector::iterator it = array->elems.begin(); it != array->elems.end(); ++it) { + for (std::vector::iterator it = array->begin(); it != array->end(); ++it) { sync_level_t level = *it; if (level.latch != latch) { continue; } - array->elems.erase(it); - array->n_elems--; + array->erase(it); mutex_exit(&sync_thread_mutex); return(TRUE); } @@ -1612,9 +1586,7 @@ sync_thread_level_arrays_free(void) /* If this slot was allocated then free the slot memory too. */ if (slot->levels != NULL) { - slot->levels->elems.erase(slot->levels->elems.begin(),slot->levels->elems.end()); - free(slot->levels); - slot->levels = NULL; + delete slot->levels; } }