Repository: ClickHouse/ClickHouse
File: src/Interpreters/CancellationChecker.cpp (C++)

Code before:
    if (it == query_set.end())
        return false;

    LOG_TEST(log, "Removing query {} from done tasks", query->getInfo().query);
    query_set.erase(it);
    return true;
}

void CancellationChecker::appendTask(const QueryStatusPtr & query, const Int64 timeout, OverflowMode overflow_mode)
{
    if (timeout <= 0) // Avoid cases when the timeout is less or equal zero
    {
        LOG_TEST(log, "Did not add the task because the timeout is 0. Query: {}", query->getInfo().query);
        return;
    }

    /// Cap timeout to 1 year to prevent overflow in chrono calculations.
    /// std::condition_variable::wait_for converts milliseconds to nanoseconds internally
    /// (multiplying by 1,000,000), which overflows for values close to INT64_MAX.
    const Int64 capped_timeout = std::min(timeout, MAX_TIMEOUT_MS);

    std::unique_lock<std::mutex> lock(m);
    LOG_TEST(log, "Added to set. query: {}, timeout: {} milliseconds", query->getInfo().query, capped_timeout);
    const auto now = std::chrono::steady_clock::now();
    const UInt64 end_time = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count() + capped_timeout;
    query_set.emplace(query, timeout, end_time, overflow_mode);
    cond_var.notify_all();
}

void CancellationChecker::appendDoneTasks(const QueryStatusPtr & query)
{
    std::unique_lock<std::mutex> lock(m);
    removeQueryFromSet(query);
    cond_var.notify_all();
}

void CancellationChecker::workerFunction()
{
    LOG_TRACE(log, "Started worker function");
    std::vector<QueryToTrack> tasks_to_cancel;

    std::unique_lock<std::mutex> lock(m);

    while (!stop_thread)
    {
        UInt64 now_ms = 0;
        std::chrono::steady_clock::duration duration_milliseconds = std::chrono::milliseconds(0);

        if (!query_set.empty())
        {
            const auto next_task_it = query_set.begin();

Review comment (bug):
`query_set.emplace` still stores the original `timeout` even though `end_time` (and the log) use `capped_timeout`. This can reintroduce overflow later if `QueryToTrack::timeout` is used in any chrono calculations (or cause inconsistent behavior/debugging). Store `capped_timeout` in the tracked entry as well (i.e., pass `capped_timeout` to `QueryToTrack`).
```suggestion
    query_set.emplace(query, capped_timeout, end_time, overflow_mode);
```

Code after:
    if (it == query_set.end())
        return false;

    LOG_TEST(log, "Removing query {} from done tasks", query->getInfo().query);
    query_set.erase(it);
    return true;
}

void CancellationChecker::appendTask(const QueryStatusPtr & query, const Int64 timeout, OverflowMode overflow_mode)
{
    if (timeout <= 0) // Avoid cases when the timeout is less or equal zero
    {
        LOG_TEST(log, "Did not add the task because the timeout is 0. Query: {}", query->getInfo().query);
        return;
    }

    /// Cap timeout to 1 year to prevent overflow in chrono calculations.
    /// std::condition_variable::wait_for converts milliseconds to nanoseconds internally
    /// (multiplying by 1,000,000), which overflows for values close to INT64_MAX.
    const Int64 capped_timeout = std::min(timeout, MAX_TIMEOUT_MS);

    std::unique_lock<std::mutex> lock(m);
    LOG_TEST(log, "Added to set. query: {}, timeout: {} milliseconds", query->getInfo().query, capped_timeout);
    const auto now = std::chrono::steady_clock::now();
    const UInt64 end_time = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count() + capped_timeout;
    query_set.emplace(query, capped_timeout, end_time, overflow_mode);
    cond_var.notify_all();
}

void CancellationChecker::appendDoneTasks(const QueryStatusPtr & query)
{
    std::unique_lock<std::mutex> lock(m);
    removeQueryFromSet(query);
    cond_var.notify_all();
}

void CancellationChecker::workerFunction()
{
    LOG_TRACE(log, "Started worker function");
    std::vector<QueryToTrack> tasks_to_cancel;

    std::unique_lock<std::mutex> lock(m);

    while (!stop_thread)
    {
        UInt64 now_ms = 0;
        std::chrono::steady_clock::duration duration_milliseconds = std::chrono::milliseconds(0);

        if (!query_set.empty())
        {
            const auto next_task_it = query_set.begin();