Description:
In extreme cases, there may be free cells in the sync_wait_array, but the function sync_array_get_and_reserve_cell fails to acquire one, leading to an abnormal crash.
The function sync_array_get_and_reserve_cell calls sync_array_get to obtain an array from the sync_wait_array.
The following code attempts to acquire elements from the sync_wait_array through a loop. However, it cannot guarantee that all elements will be accessed within the loop—some may be accessed multiple times, and in extreme cases, the same element may be retrieved every time:
for (ulint i = 0; i < sync_array_size && *cell == nullptr; ++i) {
/* Although the sync_array is get in a random way currently,
we still try at most sync_array_size times, in case any
of the sync_array we get is full */
sync_arr = sync_array_get();
*cell = sync_array_reserve_cell(sync_arr, object, type, location);
}
If the cells of this particular element are exhausted, it will ultimately lead to a crash upon exiting the loop.
How to repeat:
Modify the following function so that default_indexer_t<>::get_rnd_index() always returns a fixed value to simulate the extreme cases.
static inline sync_array_t *sync_array_get() {
if (sync_array_size <= 1) {
return (sync_wait_array[0]);
}
return (
sync_wait_array[default_indexer_t<>::get_rnd_index() % sync_array_size]);
}
Suggested fix:
use a random positon and visit all the sync_wait_array element in a loop from this position
Description: In extreme cases, there may be free cells in the sync_wait_array, but the function sync_array_get_and_reserve_cell fails to acquire one, leading to an abnormal crash. The function sync_array_get_and_reserve_cell calls sync_array_get to obtain an array from the sync_wait_array. The following code attempts to acquire elements from the sync_wait_array through a loop. However, it cannot guarantee that all elements will be accessed within the loop—some may be accessed multiple times, and in extreme cases, the same element may be retrieved every time: for (ulint i = 0; i < sync_array_size && *cell == nullptr; ++i) { /* Although the sync_array is get in a random way currently, we still try at most sync_array_size times, in case any of the sync_array we get is full */ sync_arr = sync_array_get(); *cell = sync_array_reserve_cell(sync_arr, object, type, location); } If the cells of this particular element are exhausted, it will ultimately lead to a crash upon exiting the loop. How to repeat: Modify the following function so that default_indexer_t<>::get_rnd_index() always returns a fixed value to simulate the extreme cases. static inline sync_array_t *sync_array_get() { if (sync_array_size <= 1) { return (sync_wait_array[0]); } return ( sync_wait_array[default_indexer_t<>::get_rnd_index() % sync_array_size]); } Suggested fix: use a random positon and visit all the sync_wait_array element in a loop from this position