Repository: dotnet/runtime
File: src/coreclr/debug/daccess/daccess.cpp (C++)

Code before:
    unsigned int i = 0;
    while (i < count && mIteratorIndex < mList.GetCount())
    {
        handles[i++] = mList.Get(mIteratorIndex++);
    }

    *pFetched = i;

    hr = mIteratorIndex < mList.GetCount() ? S_FALSE : S_OK;

    SOSHelperLeave();

    return hr;
}

void DacHandleWalker::WalkHandles()
{
    SUPPORTS_DAC;

    if (mEnumerated)
        return;

    mEnumerated = true;

    // The table slots are based on the number of GC heaps in the process for GC interface version < 8.
    // This is a bug, and the correct implementation is based on the number of processors starting at GC interface version 8.
    uint32_t max_slots = 1;

#ifdef FEATURE_SVR_GC
    if (GCHeapUtilities::IsServerHeap())
    {
        if (g_gcDacGlobals->minor_version_number >= 8)
            max_slots = *g_gcDacGlobals->g_totalCpuCount;
        else
            max_slots = GCHeapCount();
    }
#endif // FEATURE_SVR_GC

    DacHandleWalkerParam param(&mList);


    for (dac_handle_table_map *map = g_gcDacGlobals->handle_table_map; SUCCEEDED(param.Result) && map; map = map->pNext)
    {
        for (int i = 0; i < INITIAL_HANDLE_TABLE_ARRAY_SIZE && SUCCEEDED(param.Result); ++i)
        {
            if (map->pBuckets[i] != NULL)
            {
                for (uint32_t j = 0; j < max_slots && SUCCEEDED(param.Result); ++j)
                {
                    DPTR(dac_handle_table) hTable = map->pBuckets[i]->pTable[(int)j];
                    if (hTable)

Review comment (bug):
Just reading the comment alone, its not clear what behavior it is refering to as "this is a bug". Perhaps:


```
    // The GC sets the number of slots based on the number of processors. Prior to
    // DATAS, num_processors == GCHeapCount() for ServerGC. Unfortunately the GC DAC
    // contract didn't record the number of processors independently until minor
    // version 8 and DATAS was enabled prior to that. When using a standalone GC version
    // < 8 the DAC approximates the processor count as GCHeapCount() because we don't
    // have more accurate data to work with. This may cause handle enumeration to be
    // incomplete.
```

Code after:
    unsigned int i = 0;
    while (i < count && mIteratorIndex < mList.GetCount())
    {
        handles[i++] = mList.Get(mIteratorIndex++);
    }

    *pFetched = i;

    hr = mIteratorIndex < mList.GetCount() ? S_FALSE : S_OK;

    SOSHelperLeave();

    return hr;
}

void DacHandleWalker::WalkHandles()
{
    SUPPORTS_DAC;

    if (mEnumerated)
        return;

    mEnumerated = true;

    // The GC sets the number of slots based on the number of processors. Prior to
    // DATAS, num_processors == GCHeapCount() for ServerGC. Unfortunately the GC DAC
    // contract didn't record the number of processors independently until minor
    // version 8 and DATAS was enabled prior to that. When using a standalone GC version
    // < 8 the DAC approximates the processor count as GCHeapCount() because we don't
    // have more accurate data to work with. This may cause handle enumeration to be
    // incomplete.
    uint32_t max_slots = 1;

#ifdef FEATURE_SVR_GC
    if (GCHeapUtilities::IsServerHeap())
    {
        if (g_gcDacGlobals->minor_version_number >= 8)
            max_slots = *g_gcDacGlobals->g_totalCpuCount;
        else
            max_slots = GCHeapCount();
    }
#endif // FEATURE_SVR_GC

    DacHandleWalkerParam param(&mList);


    for (dac_handle_table_map *map = g_gcDacGlobals->handle_table_map; SUCCEEDED(param.Result) && map; map = map->pNext)
    {
        for (int i = 0; i < INITIAL_HANDLE_TABLE_ARRAY_SIZE && SUCCEEDED(param.Result); ++i)
        {
            if (map->pBuckets[i] != NULL)