Repository: ClickHouse/ClickHouse
File: src/Common/FailPoint.cpp (C++)

Code before:
{
    std::unique_lock lock(mu);
    auto iter = fail_point_wait_channels.find(fail_point_name);
    if (iter == fail_point_wait_channels.end())
        return;

    auto channel = iter->second;
    size_t my_resume_epoch = channel->resume_epoch;

    /// Wait for resume_epoch to be incremented by notify or disable
    channel->resume_cv.wait(lock, [&] {
        return channel->resume_epoch > my_resume_epoch;
    });
}

std::vector<FailPointInjection::FailPointInfo> FailPointInjection::getFailPoints()
{
    std::vector<FailPointInfo> result;
    std::lock_guard lock(mu);

#define SUB_M(NAME, TP)                                                     \
    result.push_back(                                                       \
        FailPointInfo{                                                      \
            .name = FailPoints::NAME,                                       \
            .type = FailPointType::TP,                                      \
            .enabled = fail_point_wait_channels.contains(FailPoints::NAME), \
        });
#define ADD_ONCE(NAME) SUB_M(NAME, Once)
#define ADD_REGULAR(NAME) SUB_M(NAME, Regular)
#define ADD_PAUSEABLE_ONCE(NAME) SUB_M(NAME, PauseableOnce)
#define ADD_PAUSEABLE(NAME) SUB_M(NAME, Pauseable)
    APPLY_FOR_FAILPOINTS(ADD_ONCE, ADD_REGULAR, ADD_PAUSEABLE_ONCE, ADD_PAUSEABLE)
#undef SUB_M
#undef ADD_ONCE
#undef ADD_REGULAR
#undef ADD_PAUSEABLE_ONCE
#undef ADD_PAUSEABLE

    return result;
}

#else // USE_LIBFIU

void FailPointInjection::pauseFailPoint(const String &)
{
}

void FailPointInjection::enableFailPoint(const String &)
{
}


Review comment (bug):
`fail_point_wait_channels` only includes PAUSEABLE failpoints. The others state are maintained by libfiu, maybe we can check it by `fiu_fail(...)`

Code after:
{
    std::unique_lock lock(mu);
    auto iter = fail_point_wait_channels.find(fail_point_name);
    if (iter == fail_point_wait_channels.end())
        return;

    auto channel = iter->second;
    size_t my_resume_epoch = channel->resume_epoch;

    /// Wait for resume_epoch to be incremented by notify or disable
    channel->resume_cv.wait(lock, [&] {
        return channel->resume_epoch > my_resume_epoch;
    });
}

std::vector<FailPointInjection::FailPointInfo> FailPointInjection::getFailPoints()
{
    std::vector<FailPointInfo> result;

#define SUB_M(NAME, TP)                                 \
    result.push_back(                                   \
        FailPointInfo{                                  \
            .name = FailPoints::NAME,                   \
            .type = FailPointType::TP,                  \
            .enabled = fiu_fail(FailPoints::NAME) != 0, \
        });
#define ADD_ONCE(NAME) SUB_M(NAME, Once)
#define ADD_REGULAR(NAME) SUB_M(NAME, Regular)
#define ADD_PAUSEABLE_ONCE(NAME) SUB_M(NAME, PauseableOnce)
#define ADD_PAUSEABLE(NAME) SUB_M(NAME, Pauseable)
    APPLY_FOR_FAILPOINTS(ADD_ONCE, ADD_REGULAR, ADD_PAUSEABLE_ONCE, ADD_PAUSEABLE)
#undef SUB_M
#undef ADD_ONCE
#undef ADD_REGULAR
#undef ADD_PAUSEABLE_ONCE
#undef ADD_PAUSEABLE

    return result;
}

#else // USE_LIBFIU

void FailPointInjection::pauseFailPoint(const String &)
{
}

void FailPointInjection::enableFailPoint(const String &)
{
}

void FailPointInjection::enablePauseFailPoint(const String &, UInt64)