Skip to content

24.8.14 Backport of #75474 - Stricter checks when attaching/detaching threads to groups - #2016

Merged
zvonand merged 2 commits into
customizations/24.8.14from
backports/24.8.14/75474
Jul 21, 2026
Merged

24.8.14 Backport of #75474 - Stricter checks when attaching/detaching threads to groups#2016
zvonand merged 2 commits into
customizations/24.8.14from
backports/24.8.14/75474

Conversation

@ilejn

@ilejn ilejn commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

Changelog category (leave one):

  • Not for changelog (changelog entry is not required)

Closes ClickHouse#59114

In https://s3.amazonaws.com/clickhouse-test-reports/74014/dcdccd54f13e74c5018f6d40e5a4caa77858dc22/stress_test__debug_.html CurrentThread::getGroup() returned nullptr when called from TCPHandler::processOrdinaryQuery. This means that calls to CurrentThread::attachToGroup/detachFromGroupIfNotDetached are not properly nested: someone detached a thread that they didn't attach. (The thread is expected to be attached to a group because the caller of processOrdinaryQuery holds a QueryScope for the duration of the call.)

Almost all calls to CurrentThread::attachToGroupIfDetached/detachFromGroupIfNotDetached follow this pattern that looks incorrect:

    auto thread_func = [thread_group = CurrentThread::getGroup()]
    {
        SCOPE_EXIT_SAFE(
            if (thread_group)
                CurrentThread::detachFromGroupIfNotDetached();
        );

        if (thread_group)
            CurrentThread::attachToGroupIfDetached(thread_group);

        ...
    };

If the thread is already attached to a group, it'll end up detached after this function returns. Normally such thread_func is immediately scheduled on a thread pool; then the thread shouldn't be already attached to a group (... or so I'm assuming; there were no asserts about this, so CI on this PR may prove this analysis wrong). But some code sites sometimes call such function directly, e.g. Aggregator::prepareBlocksAndFillTwoLevelImpl. AFAICT, this would incorrectly detach the thread from the thread group. I'm guessing this is what caused these test failures (but I didn't try to reproduce this and don't have an explanation for why the crash happens so rarely.)

This PR replaces this pattern with a more correct one, with a bunch of asserts, wrapped in a RAII thing.

Most changes are mechanical. Most substantial ones are in ThreadStatus.h, ThreadStatusExt.cpp, and ProfileEventsExt.cpp.

(ClickHouse#75474 by @al13n321)

CI/CD Options

Exclude tests:

  • Fast test
  • Integration Tests
  • Stateless tests
  • Stateful tests
  • Performance tests
  • Aarch64 tests
  • All with ASAN
  • All with TSAN
  • All with MSAN
  • All with UBSAN
  • All with Coverage
  • All Regression
  • Disable CI Cache

Regression jobs to run:

  • Fast suites (mostly <1h)
  • Aggregate Functions (2h)
  • Alter (1.5h)
  • Benchmark (30m)
  • ClickHouse Keeper (1h)
  • Iceberg (2h)
  • LDAP (1h)
  • OAuth (5m)
  • Parquet (1.5h)
  • RBAC (1.5h)
  • SSL Server (1h)
  • S3 (2h)
  • S3 Export (2h)
  • Swarms (30m)
  • Tiered Storage (2h)

Stricter checks when attaching/detaching threads to groups

Signed-off-by: Ilya Golshtein <igolshtein@altinity.com>
@altinity-robot

altinity-robot commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

This is an automated comment for commit f7498e9 with description of existing statuses. It's updated for the latest CI running

❌ Click here to open a full report in a separate page

Check nameDescriptionStatus
Integration testsThe integration tests report. In parenthesis the package type is given, and in square brackets are the optional part/total tests❌ failure
Successful checks
Check nameDescriptionStatus
AST fuzzerRuns randomly generated queries to catch program errors. The build type is optionally given in parenthesis. If it fails, ask a maintainer for help✅ success
BuildsThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Compatibility checkChecks that clickhouse binary runs on distributions with old libc versions. If it fails, ask a maintainer for help✅ success
Docker keeper imageThe check to build and optionally push the mentioned image to docker hub✅ success
Docker server imageThe check to build and optionally push the mentioned image to docker hub✅ success
Grype Scan altinityinfra/clickhouse-keeper:2016-24.8.14.10546.altinitytestThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Grype Scan altinityinfra/clickhouse-server:2016-24.8.14.10546.altinitytest-alpineThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Grype Scan altinityinfra/clickhouse-server:2016-24.8.14.10546.altinitytestThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Install packagesChecks that the built packages are installable in a clear environment✅ success
Ready for releaseThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release aes_encryptionThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release aggregate_functions_1There's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release aggregate_functions_2There's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release aggregate_functions_3There's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release alter_attach_1There's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release alter_attach_2There's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release alter_moveThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release alter_replaceThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release atomic_insertThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release base_58There's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release benchmark_aws_s3There's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release benchmark_gcsThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release benchmark_minioThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release clickhouse_keeper_failoverThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release clickhouse_keeper_no_ssl_1There's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release clickhouse_keeper_no_ssl_2There's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release clickhouse_keeper_ssl_1There's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release clickhouse_keeper_ssl_2There's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release data_typesThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release datetime64_extended_rangeThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release disk_level_encryptionThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release dnsThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release enginesThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release exampleThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release extended_precision_data_typesThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release functionsThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release iceberg_1There's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release iceberg_2There's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release jwt_authenticationThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release kafkaThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release kerberosThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release key_valueThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release ldap_authenticationThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release ldap_external_user_directoryThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release ldap_role_mappingThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release lightweight_deleteThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release memoryThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release parquetThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release parquet_aws_s3There's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release parquet_minioThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release part_moves_between_shardsThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release rbac_1There's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release rbac_2There's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release rbac_3There's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release s3_aws_s3_1There's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release s3_aws_s3_2There's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release s3_azure_1There's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release s3_azure_2There's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release s3_export_partThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release s3_export_partitionThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release s3_gcs_1There's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release s3_gcs_2There's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release s3_minio_1There's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release s3_minio_2There's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release s3_minio_3There's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release selectsThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release session_timezoneThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release settingsThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release ssl_server_1There's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release ssl_server_2There's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release ssl_server_3There's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release swarmsThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release tiered_storage_localThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release tiered_storage_minioThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release tiered_storage_s3amazonThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release tiered_storage_s3gcsThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release versionThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Regression release window_functionsThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Sign releaseThere's no description for the check yet, please add it to tests/ci/ci_config.py:CHECK_DESCRIPTIONS✅ success
Stateful testsRuns stateful functional tests for ClickHouse binaries built in various configurations -- release, debug, with sanitizers, etc✅ success
Stateless testsRuns stateless functional tests for ClickHouse binaries built in various configurations -- release, debug, with sanitizers, etc✅ success
Stress testRuns stateless functional tests concurrently from several clients to detect concurrency-related errors✅ success

@zvonand zvonand left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, almost identical to original one.

@zvonand

zvonand commented Jul 15, 2026

Copy link
Copy Markdown
Member

@ilejn can we (you) verify it or we need attention from QA?

@ilejn

ilejn commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator Author

@ilejn can we (you) verify it or we need attention from QA?

It is not trivial to reproduce. I think the choice is between 'me' and 'nobody', no reasons to involve QA.
Let's start from 'me'.

@CarlosFelipeOR

Copy link
Copy Markdown
Collaborator

AI audit note: This review comment was generated by AI (gpt-5.3-codex).

Audit update for PR #2016 (thread-group attach/detach refactor and callsite migration):

Confirmed defects:

  • Medium: ThreadGroupSwitcher suppresses attach-transition exceptions and can continue with inconsistent thread-group state
    • Impact: work can proceed detached from the expected ThreadGroup, causing wrong memory/profile accounting and broken group restoration across thread-pool task boundaries.
    • Anchor: src/Interpreters/ThreadStatusExt.cpp / ThreadGroupSwitcher; reachable from src/Storages/MergeTree/MergePlainMergeTreeTask.cpp, src/Storages/MergeTree/MutatePlainMergeTreeTask.cpp, src/Storages/MergeTree/ReplicatedMergeMutateTaskBase.cpp (allow_existing_group = true).
    • Trigger: existing group is detached, then CurrentThread::attachToGroup throws during switch (for example, attach-path logical/OS exception).
    • Why defect: constructor catches all exceptions, logs, nulls rollback fields, and returns; caller continues execution, while destructor becomes a no-op and cannot restore prior group.
    • Fix direction (short): in ThreadGroupSwitcher, make ctor rollback-safe (restore previous group on failure) and avoid fail-open continuation after failed switch.
    • Regression test direction (short): fault-inject exception in attach path and assert previous group is restored and task does not continue under wrong group state.

Coverage summary:

  • Scope reviewed: all 29 changed files, with full call-graph focus on thread-pool entrypoints -> ThreadGroupSwitcher transitions -> detach/restore, plus ThreadPool post-job invariants and ProfileEventsExt guards.
  • Categories failed: exception-safety/partial-rollback for group transition.
  • Categories passed: shared-state race/deadlock risk in changed paths, iterator/reference invalidation, integer/signedness issues, ownership/RAII leaks, fail-open/fail-closed checks in added guards.
  • Assumptions/limits: static audit only (diff + surrounding code context), no runtime fault-injection execution.

@CarlosFelipeOR

Copy link
Copy Markdown
Collaborator

@ilejn, I saw your comment. Since this PR was assigned to me, I went ahead and performed an AI-driven QA verification, focused mainly on the CI. Please find the QA Verification below — let me know if you'd like to run any further tests or validation before I add the verified label.

QA Verification — ✅ Approved

This PR is a faithful backport of upstream #75474 (already merged upstream) and does not introduce any regression. The most relevant CI configs for a threading fix — debug build + Stress test (debug), the exact config where the original crash surfaced — passed clean, and all sanitizer builds compiled successfully. The two remaining CI failures are environmental and unrelated to this change.

Summary

Item Result
Diff vs upstream ClickHouse#75474 ✅ Faithful — core RAII logic identical, divergences cosmetic/base-driven
File coverage ✅ All applicable sites converted; the 2 upstream files not touched don't exist / aren't applicable in 24.8.14
Stress test (debug) ✅ "No errors found" (asserts active, high-concurrency — the original crash config)
Stateless/Stateful/AST-fuzzer (debug) ✅ Pass (new chassert asserts active, no trips)
Sanitizer builds (ASAN/TSAN/MSAN/UBSAN/aarch64) ✅ All compile clean (test execution excluded per PR options)
Functional/Integration/Regression (release) ✅ Pass
Integration tests (release) [2/4] ⚠️ Non-blocking — job timeout (12000s), all groups parallel0–6 FAILED=0/ERROR=0; batch-balancing, not a test failure
GrypeScan (keeper/server/-alpine) ⚠️ Non-blocking — Ubuntu base-image CVEs, fixed in #2062 (merged); unrelated to this PR

Evidence

1. Backport fidelity (vs upstream ClickHouse#75474)
The core ThreadGroupSwitcher RAII + asserts logic is byte-identical to upstream, all 29 sites are converted with the same transformation, and every divergence is cosmetic or driven by the older 24.8.14 base (the 2 upstream-only files aren't applicable in 24.8.14).

2. CI triage

  • Integration tests (release) [2/4]: Job timeout expired, fail: 0, passed: 712. Wrapper hit the 12000s limit and got SIGTERM (exit -15 → GH 241). A rerun should confirm timing variance; if consistent, the timeout should be raised or tests redistributed.
  • GrypeScan failures: base-image Ubuntu CVEs, addressed by Stable 24.8: Fix Grype scan and Ubuntu package CVEs #2062 (merged) — not caused by this PR's C++ changes.

3. On the AI audit note (fail-open in ThreadGroupSwitcher ctor)
This is byte-identical to upstream ClickHouse#75474 — a deliberate noexcept design choice (upstream comments it as "Unexpected. For caller's convenience avoid throwing exceptions"), not introduced by this backport. The trigger is also guarded: LockMemoryExceptionInThread suppresses memory-tracker exceptions right before attachToGroup, and the previous (pre-PR) pattern had no exception handling at all. Out of scope for this backport; if considered a real concern it should be raised upstream.

Note: ASAN/TSAN/MSAN/UBSAN test execution was excluded via PR options. Given the fix is upstream-validated, the backport is faithful, and debug+stress (asserts active) passed, residual risk is low. The full sanitizer matrix will run on merge.

@ilejn

ilejn commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator Author

Hello @CarlosFelipeOR , thanks for the audit.
I agree that suppressing exceptions is not perfect.
In recent master this logic is slightly improved, although constructor is still noexcept, which seems a valid decision.

The improvements are in ClickHouse#105417 and ClickHouse#106462
I don't think that we have to backport these PRs to 24.8 unless it is requested specifically.

So I treat audit as positive.

@CarlosFelipeOR CarlosFelipeOR added stable verified Approved for release labels Jul 21, 2026
@zvonand
zvonand merged commit bfc3c2d into customizations/24.8.14 Jul 21, 2026
358 of 369 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants