Bug #119585 In extreme cases, sync_array_get_and_reserve_cell fails to obtain a cell even have space
Submitted: 23 Dec 3:17
Reporter: yuxiang jiang Email Updates:
Status: Open Impact on me:
None 
Category:MySQL Server: InnoDB storage engine Severity:S3 (Non-critical)
Version:8.0.30/9.4.0/8.4.6 OS:Any
Assigned to: CPU Architecture:Any

[23 Dec 3:17] yuxiang jiang
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
[23 Dec 5:43] Knut Anders Hatlen
Thank you for the bug report. The functions you refer to seem to be in the InnoDB code, so I'm changing the bug category to InnoDB.