Skip to content

Avoid data race in grpc alarm (#10124) - #11030

Open
ti-chi-bot wants to merge 1 commit into
pingcap:release-8.5from
ti-chi-bot:cherry-pick-10124-to-release-8.5
Open

Avoid data race in grpc alarm (#10124)#11030
ti-chi-bot wants to merge 1 commit into
pingcap:release-8.5from
ti-chi-bot:cherry-pick-10124-to-release-8.5

Conversation

@ti-chi-bot

@ti-chi-bot ti-chi-bot commented Aug 10, 2026

Copy link
Copy Markdown
Member

This is an automated cherry-pick of #10124

What problem does this PR solve?

Issue Number: close #10107

Problem Summary:

In current implementation, Alarm is hold by MPPGatherTaskSet, and in MPPTaskManager::abortMPPGather, all the Alarm will be deconstructed since it call gather_task_set->alarms.clear();
But when gather_task_set->alarms.clear(); is called, the EstablishCallData may still inside grpc's core, and it hold a raw pointer of AlarmImpl, although inside AlarmImpl, it use atomic to try to make it thread-safe

 void Ref() { gpr_ref(&refs_); }
  void Unref() {
    if (gpr_unref(&refs_)) {
      delete this;
    }
  }

But Unref/Ref is not thread safe because in grpc's implementation, if EstablishCallData is put back to grpc's core, it does not call Ref immediately, instead, looks like grpc only call Ref if some event happens:

 void Set(::grpc::CompletionQueue* cq, gpr_timespec deadline, void* tag) {
    grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
    grpc_core::ExecCtx exec_ctx;
    GRPC_CQ_INTERNAL_REF(cq->cq(), "alarm");
    cq_ = cq->cq();
    tag_ = tag;
    GPR_ASSERT(grpc_cq_begin_op(cq_, this));
    GRPC_CLOSURE_INIT(
        &on_alarm_,
        [](void* arg, grpc_error_handle error) {
          // queue the op on the completion queue
          AlarmImpl* alarm = static_cast<AlarmImpl*>(arg);
          alarm->Ref();
          // Preserve the cq and reset the cq_ so that the alarm
          // can be reset when the alarm tag is delivered.
          grpc_completion_queue* cq = alarm->cq_;
          alarm->cq_ = nullptr;
          grpc_cq_end_op(
              cq, alarm, error,
              [](void* /*arg*/, grpc_cq_completion* /*completion*/) {}, arg,
              &alarm->completion_);
          GRPC_CQ_INTERNAL_UNREF(cq, "alarm");
        },
        this, grpc_schedule_on_exec_ctx);
    grpc_timer_init(&timer_, grpc_timespec_to_millis_round_up(deadline),
                    &on_alarm_);
  }

So there is a case that 2 threads try to delete the AlarmImpl concurrently.

Time thread 1 thread 2
1 call gpr_unref(&refs_)
2 gpr_unref(&refs_) return true(refs is 0)
3 call Ref()
4 call delete this
5 call Unref(), and it will also try to delete this

What is changed and how it works?

This pr let EstablishCallData to hold the alarm, so it will never be constructed when EstablishCallData is inside grpc's core.


Check List

Tests

  • Unit test
  • Integration test
  • Manual test (add detailed scripts or steps below)
  • No code

Side effects

  • Performance regression: Consumes more CPU
  • Performance regression: Consumes more Memory
  • Breaking backward compatibility

Documentation

  • Affects user behaviors
  • Contains syntax changes
  • Contains variable changes
  • Contains experimental features
  • Changes MySQL compatibility

Release note

None

Summary by CodeRabbit

  • Bug Fixes
    • Improved cancellation and cleanup handling for distributed task operations.
    • Refined alarm and wait-state management to support more reliable tunnel coordination.
    • Reduced the risk of lingering asynchronous operations during task cancellation or failure.

Signed-off-by: ti-chi-bot <ti-community-prow-bot@tidb.io>
@ti-chi-bot ti-chi-bot added do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. release-note-none Denotes a PR that doesn't merit a release note. size/S Denotes a PR that changes 10-29 lines, ignoring generated files. type/cherry-pick-for-release-8.5 This PR is cherry-picked to release-8.5 from a source PR. labels Aug 10, 2026
@ti-chi-bot ti-chi-bot mentioned this pull request Aug 10, 2026
12 tasks
@ti-chi-bot

ti-chi-bot Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

This cherry pick PR is for a release branch and has not yet been approved by triage owners.
Adding the do-not-merge/cherry-pick-not-approved label.

To merge this cherry pick:

  1. It must be LGTMed and approved by the reviewers firstly.
  2. For pull requests to TiDB-x branches, it must have no failed tests.
  3. AFTER it has lgtm and approved labels, please wait for the cherry-pick merging approval from triage owners.
Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@ti-chi-bot

Copy link
Copy Markdown
Member Author

@solotzg This PR has conflicts, I have hold it.
Please resolve them or ask others to resolve them, then comment /unhold to remove the hold label.

@ti-chi-bot

ti-chi-bot Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

@ti-chi-bot: ## If you want to know how to resolve it, please read the guide in TiDB Dev Guide.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the ti-community-infra/tichi repository.

@ti-chi-bot

ti-chi-bot Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign calvinneo for approval. For more information see the Code Review Process.
Please ensure that each of them provides their approval before proceeding.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The change adds a call-owned gRPC alarm accessor. MPP gather tracking stores references to these alarms and uses them during tunnel waiting and alarm cancellation. The waiting-tunnel block contains unresolved merge-conflict markers.

Changes

Alarm lifetime handling

Layer / File(s) Summary
Expose call-owned alarms
dbms/src/Flash/EstablishCall.h, dbms/src/Flash/EstablishCall.cpp
EstablishCallData now owns a default-initialized grpc::Alarm and exposes it through getAlarm().
Track and cancel alarm references
dbms/src/Flash/Mpp/MPPTaskManager.h, dbms/src/Flash/Mpp/MPPTaskManager.cpp
MPPGatherTaskSet::alarms now stores std::reference_wrapper<grpc::Alarm> values. Tunnel waiting registers the call alarm reference, and cancellation paths invoke Cancel() through that reference. The changed tunnel block contains unresolved merge-conflict markers.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Poem

I’m a rabbit with an alarm in my ear,
Call-owned timing now stays near.
Gather paths hold references tight,
Cancellation follows the light.
Conflict marks still scratch the burrow wall—
Please clear them before the final call.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The changes address alarm lifetime, but merge-conflict markers remain and no ThreadSanitizer validation evidence is provided. Resolve all merge conflicts, then run and report the ComputeServerRunner_testErrorMessage reproduction under ThreadSanitizer.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the primary change: preventing a data race involving gRPC alarms.
Description check ✅ Passed The description covers the problem, issue, implementation, checklist, side effects, documentation, and release note sections.
Out of Scope Changes check ✅ Passed The changed files and alarm ownership updates are related to the linked issue and no unrelated code changes are identified.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@dbms/src/Flash/Mpp/MPPTaskManager.cpp`:
- Around line 250-259: Resolve the conflict in the MPP task setup by removing
all merge markers and retaining the race-safe alarm retrieval via
EstablishCallData::getAlarm() and std::ref(alarm). Update EstablishCallData’s
public API in EstablishCall.h so the call uses the existing public
setToWaitingTunnelState() behavior, or otherwise exposes an equivalent valid
transition without referencing private WAIT_TUNNEL or unavailable
setCallStateAndUpdateMetrics().
- Line 258: Resolve the remaining merge-conflict markers in findAsyncTunnel(),
preserving the intended gather_task_set->alarms insertion involving
sender_task_id, receiver_task_id, and alarm. Remove all conflict markers and
ensure the resulting C++ block is syntactically valid and compilable.

In `@dbms/src/Flash/Mpp/MPPTaskManager.h`:
- Line 46: Update the alarms storage in MPPTaskManager and the abortMPPGather
cancellation flow so each grpc::Alarm remains owned, along with its
EstablishCallData owner, until the completion queue removes the alarm; do not
erase a non-owning reference while the alarm may still be used. Preserve
cancellation behavior and run the ComputeServerRunner_testErrorMessage
ThreadSanitizer reproduction after resolving the merge conflict.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 4960dcca-c719-43ec-a1a3-67cb32d02089

📥 Commits

Reviewing files that changed from the base of the PR and between 76536b2 and cb6c2cb.

📒 Files selected for processing (4)
  • dbms/src/Flash/EstablishCall.cpp
  • dbms/src/Flash/EstablishCall.h
  • dbms/src/Flash/Mpp/MPPTaskManager.cpp
  • dbms/src/Flash/Mpp/MPPTaskManager.h

Comment on lines +250 to +259
<<<<<<< HEAD
auto & alarm = gather_task_set->alarms[sender_task_id][receiver_task_id];
call_data->setToWaitingTunnelState();
=======
auto & alarm = call_data->getAlarm();
call_data->setCallStateAndUpdateMetrics(
EstablishCallData::WAIT_TUNNEL,
GET_METRIC(tiflash_establish_calldata_count, type_wait_tunnel_calldata));
gather_task_set->alarms[sender_task_id].emplace(receiver_task_id, std::ref(alarm));
>>>>>>> 262b942077 (Avoid data race in grpc alarm (#10124))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="dbms/src/Flash/Mpp/MPPTaskManager.cpp"

if rg -n '^(<<<<<<<|=======|>>>>>>>)' "$file"; then
  echo "Unresolved merge conflict markers found" >&2
  exit 1
fi

rg -n -C 3 \
  'setCallStateAndUpdateMetrics|WAIT_TUNNEL|setToWaitingTunnelState|getAlarm|alarms.*emplace' \
  dbms/src/Flash/EstablishCall.h \
  "$file"

Repository: pingcap/tiflash

Length of output: 286


🏁 Script executed:

#!/bin/bash
set -u

echo "== file section =="
sed -n '230,280p' dbms/src/Flash/Mpp/MPPTaskManager.cpp 2>/dev/null || true

echo "== EstablishCall.h related section =="
sed -n '1,220p' dbms/src/Flash/EstablishCall.h 2>/dev/null || true

echo "== other relevant files =="
git ls-files | rg 'dbms/src/Flash/.*\.(h|cpp|hpp)$' | sed -n '1,120p'

echo "== search for API names =="
rg -n 'setCallStateAndUpdateMetrics|WAIT_TUNNEL|setToWaitingTunnelState|getAlarm|type_wait_tunnel_calldata|tiflash_establish_calldata_count' dbms/src/Flash 2>/dev/null || true

Repository: pingcap/tiflash

Length of output: 14831


🏁 Script executed:

#!/bin/bash
set -u

echo "== MPPTaskManager outline == "
ast-grep outline dbms/src/Flash/Mpp/MPPTaskManager.cpp --view compact 2>/dev/null || true

echo "== alarms declarations and usages in MPPTaskManager.cpp =="
rg -n -C 2 'gather_task_set->alarms|sender_task_id|receiver_task_id|\.Set\(|std::ref\(alarm\)|type_wait_tunnel_calldata' dbms/src/Flash/Mpp/MPPTaskManager.cpp

echo "== EstablishCall related symbols =="
rg -n -C 2 'WAIT_TUNNEL|getAlarm|setToWaitingTunnelState|setCallStateAndUpdateMetrics|type_wait_tunnel_calldata|tiflash_establish_calldata_count|GET_METRIC' dbms/src/Flash/EstablishCall.h dbms/src/Flash/EstablishCall.cpp dbms/src/Metrics 2>/dev/null || true

echo "== changed conflict metadata =="
git diff --stat || true
git diff --name-status || true

Repository: pingcap/tiflash

Length of output: 6465


Resolve the unresolved merge conflict at MPPTaskManager.cpp:250-259.

The conflict markers remain in the build file, so MPPTaskManager.cpp does not compile. The incoming branch also calls setCallStateAndUpdateMetrics() and EstablishCallData::WAIT_TUNNEL, but dbms/src/Flash/EstablishCall.h exposes setToWaitingTunnelState() and keeps WAIT_TUNNEL private; getAlarm() is available, so keep std::ref(alarm) as intended and update the public API instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@dbms/src/Flash/Mpp/MPPTaskManager.cpp` around lines 250 - 259, Resolve the
conflict in the MPP task setup by removing all merge markers and retaining the
race-safe alarm retrieval via EstablishCallData::getAlarm() and std::ref(alarm).
Update EstablishCallData’s public API in EstablishCall.h so the call uses the
existing public setToWaitingTunnelState() behavior, or otherwise exposes an
equivalent valid transition without referencing private WAIT_TUNNEL or
unavailable setCallStateAndUpdateMetrics().

call_data->setCallStateAndUpdateMetrics(
EstablishCallData::WAIT_TUNNEL,
GET_METRIC(tiflash_establish_calldata_count, type_wait_tunnel_calldata));
gather_task_set->alarms[sender_task_id].emplace(receiver_task_id, std::ref(alarm));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -C 8 \
  'EstablishMPPConnection|findAsyncTunnel|sender_meta\(\).*task_id|receiver_meta\(\).*task_id' .

Repository: pingcap/tiflash

Length of output: 50026


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== MPPTaskManager relevant sections =="
sed -n '170,255p;360,395p' dbms/src/Flash/Mpp/MPPTaskManager.cpp

echo
echo "== MPPTaskManager.h gather_task_set / alarm declarations =="
sed -n '180,230p' dbms/src/Flash/Mpp/MPPTaskManager.h

echo
echo "== Find MPPGatherTaskSet definition and alarm methods =="
rg -n -C 4 'struct MPPGatherTaskSet|class MPPGatherTaskSet|alarms|hasAlarm|notifyAlarm|Cancel\\(' dbms/src/Flash/Mpp

Repository: pingcap/tiflash

Length of output: 6992


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== MPPTaskManager.h declarations =="
sed -n '1,140p' dbms/src/Flash/Mpp/MPPTaskManager.h
sed -n '140,190p' dbms/src/Flash/Mpp/MPPTaskManager.h
sed -n '190,270p' dbms/src/Flash/Mpp/MPPTaskManager.h

echo
echo "== findAsyncTunnel full and concurrent merge markers =="
sed -n '204,300p' dbms/src/Flash/Mpp/MPPTaskManager.cpp

echo
echo "== alarm-related symbols and Cancel references =="
rg -n -C 3 'alarms|hasAlarm|notifyAlarm|setAlarm|Cancel\(' dbms/src/Flash dbms/src/Core 2>/dev/null || true

echo
echo "== compile marker check =="
python3 - <<'PY'
from pathlib import Path
p=Path('dbms/src/Flash/Mpp/MPPTaskManager.cpp')
for i,line in enumerate(p.read_text().splitlines(),1):
    if line.startswith('<'):
        print(i, line)
PY

Repository: pingcap/tiflash

Length of output: 25014


Resolve the merge conflict in findAsyncTunnel().

dbms/src/Flash/Mpp/MPPTaskManager.cpp:250-259 still contains unresolved conflict markers, so this translation unit will not compile.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@dbms/src/Flash/Mpp/MPPTaskManager.cpp` at line 258, Resolve the remaining
merge-conflict markers in findAsyncTunnel(), preserving the intended
gather_task_set->alarms insertion involving sender_task_id, receiver_task_id,
and alarm. Remove all conflict markers and ensure the resulting C++ block is
syntactically valid and compilable.

String error_message;
/// <sender_task_id, <receiver_task_id, alarm>>
std::unordered_map<Int64, std::unordered_map<Int64, grpc::Alarm>> alarms;
std::unordered_map<Int64, std::unordered_map<Int64, std::reference_wrapper<grpc::Alarm>>> alarms;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -C 8 \
  'delete this|EstablishCallData::~|getAlarm\(\)|alarms|cancelAlarmsBySenderTaskId|abortMPPGather|Cancel\(\)' \
  dbms/src/Flash/EstablishCall.h \
  dbms/src/Flash/EstablishCall.cpp \
  dbms/src/Flash/Mpp/MPPTaskManager.h \
  dbms/src/Flash/Mpp/MPPTaskManager.cpp

rg -n -C 4 \
  'ComputeServerRunner_testErrorMessage|testErrorMessage|ThreadSanitizer|TSAN' .

Repository: pingcap/tiflash

Length of output: 31996


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the relevant class definitions, methods, and exact call sites using small targeted reads.
printf '--- MPPTaskManager.h outline ---\n'
ast-grep outline dbms/src/Flash/Mpp/MPPTaskManager.h --view compact || true

printf '--- MPPTaskManager.h relevant lines ---\n'
sed -n '1,110p' dbms/src/Flash/Mpp/MPPTaskManager.h
sed -n '240,275p' dbms/src/Flash/Mpp/MPPTaskManager.h

printf '--- MPPTaskManager.cpp relevant lines ---\n'
sed -n '35,70p' dbms/src/Flash/Mpp/MPPTaskManager.cpp
sed -n '230,310p' dbms/src/Flash/Mpp/MPPTaskManager.cpp
sed -n '344,405p' dbms/src/Flash/Mpp/MPPTaskManager.cpp
sed -n '488,525p' dbms/src/Flash/Mpp/MPPTaskManager.cpp

printf '--- EstablishCall.h relevant lines ---\n'
sed -n '1,130p' dbms/src/Flash/EstablishCall.h

printf '--- EstablishCall.cpp relevant lines ---\n'
sed -n '62,145p' dbms/src/Flash/EstablishCall.cpp
sed -n '140,190p' dbms/src/Flash/EstablishCall.cpp
sed -n '270,340p' dbms/src/Flash/EstablishCall.cpp

printf '--- Tests relevant lines ---\n'
sed -n '1354,1430p' dbms/src/Flash/tests/gtest_compute_server.cpp

printf '--- Deterministic control-flow extraction ---\n'
python3 - <<'PY'
from pathlib import Path
for path in [
    Path('dbms/src/Flash/Mpp/MPPTaskManager.cpp'),
    Path('dbms/src/Flash/Mpp/MPPTaskManager.h'),
    Path('dbms/src/Flash/EstablishCall.cpp'),
    Path('dbms/src/Flash/EstablishCall.h'),
    Path('dbms/src/Flash/tests/gtest_compute_server.cpp'),
]:
    text = path.read_text()
    print(f'## {path}')
    for needle in [
        'std::reference_wrapper<grpc::Alarm> alarms',
        'cancelAlarmsBySenderTaskId',
        'markTaskAsFinishedOrFailed',
        'abortMPPGather',
        'alarm.second.get().Cancel()',
        'gather_task_set->alarms.clear()',
        'gather_task_set->alarms[sender_task_id].emplace(receiver_task_id, std::ref(alarm))',
        'call_data->getAlarm()',
        'delete this;',
        'tryConnectTunnel()',
        'async_tunnel_sender->setResult',
        'ComputeServerRunner',
        'testErrorMessage',
    ]:
        idx = text.find(needle)
        if idx == -1:
            continue
        line = text[:idx].count('\n') + 1
        print(f'line {line}: {needle}')
PY

Repository: pingcap/tiflash

Length of output: 244


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the relevant class definitions, methods, and exact call sites using small targeted reads.
printf '%s\n' '--- MPPTaskManager.h outline ---'
ast-grep outline dbms/src/Flash/Mpp/MPPTaskManager.h --view compact || true

printf '%s\n' '--- MPPTaskManager.h relevant lines ---'
sed -n '1,110p' dbms/src/Flash/Mpp/MPPTaskManager.h
sed -n '240,275p' dbms/src/Flash/Mpp/MPPTaskManager.h

printf '%s\n' '--- MPPTaskManager.cpp relevant lines ---'
sed -n '35,70p' dbms/src/Flash/Mpp/MPPTaskManager.cpp
sed -n '230,310p' dbms/src/Flash/Mpp/MPPTaskManager.cpp
sed -n '344,405p' dbms/src/Flash/Mpp/MPPTaskManager.cpp
sed -n '488,525p' dbms/src/Flash/Mpp/MPPTaskManager.cpp

printf '% s\n' '--- EstablishCall.h relevant lines ---'
sed -n '1,130p' dbms/src/Flash/EstablishCall.h

printf '%s\n' '--- EstablishCall.cpp relevant lines ---'
sed -n '62,145p' dbms/src/Flash/EstablishCall.cpp
sed -n '140,190p' dbms/src/Flash/EstablishCall.cpp
sed -n '270,340p' dbms/src/Flash/EstablishCall.cpp

printf '% s\n' '--- Tests relevant lines ---'
sed -n '1354,1430p' dbms/src/Flash/tests/gtest_compute_server.cpp

printf '%s\n' '--- Deterministic control-flow extraction ---'
python3 - <<'PY'
from pathlib import Path
for path in [
    Path('dbms/src/Flash/Mpp/MPPTaskManager.cpp'),
    Path('dbms/src/Flash/Mpp/MPPTaskManager.h'),
    Path('dbms/src/Flash/EstablishCall.cpp'),
    Path('dbms/src/Flash/EstablishCall.h'),
    Path('dbms/src/Flash/tests/gtest_compute_server.cpp'),
]:
    text = path.read_text()
    print(f'## {path}')
    for needle in [
        'std::reference_wrapper<grpc::Alarm> alarms',
        'cancelAlarmsBySenderTaskId',
        'markTaskAsFinishedOrFailed',
        'abortMPPGather',
        'alarm.second.get().Cancel()',
        'gather_task_set->alarms.clear()',
        'gather_task_set->alarms[sender_task_id].emplace(receiver_task_id, std::ref(alarm))',
        'call_data->getAlarm()',
        'delete this;',
        'tryConnectTunnel()',
        'async_tunnel_sender->setResult',
        'ComputeServerRunner',
        'testErrorMessage',
    ]:
        idx = text.find(needle)
        if idx == -1:
            continue
        line = text[:idx].count('\n') + 1
        print(f'line {line}: {needle}')
PY

Repository: pingcap/tiflash

Length of output: 30566


🏁 Script executed:

#!/bin/bash
set -euo pipesse

printf '%s\n' '--- EstablishCall.h tail members ---'
sed -n '130,185p' dbms/src/Flash/EstablishCall.h

printf '%s\n' '--- EstablishCall.cpp writeDone ---'
sed -n '310,380p' dbms/src/Flash/EstablishCall.cpp

printf '%s\n' '--- MPPTaskManager.cpp getMPPQueryAndGatherTaskSet ---'
sed -n '310,350p' dbms/src/Flash/Mpp/MPPTaskManager.cpp
sed -n '525,580p' dbms/src/Flash/Mpp/MPPTaskManager.cpp

printf '%s\n' '--- MPPTaskManager.h gather definitions ---'
sed -n '53,180p' dbms/src/Flash/Mpp/MPPTaskManager.h

printf '%s\n' '--- cancelGather calls ---'
rg -n -C 6 'cancelGather' .

Repository: pingcap/tiflash

Length of output: 201


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- EstablishCall.h tail members ---'
sed -n '130,185p' dbms/src/Flash/EstablishCall.h

printf '%s\n' '--- EstablishCall.cpp writeDone ---'
sed -n '310,380p' dbms/src/Flash/EstablishCall.cpp

printf '%s\n' '--- MPPTaskManager.cpp cleanup helpers ---'
sed -n '310,350p' dbms/src/Flash/Mpp/MPPTaskManager.cpp
sed -n '525,580p' dbms/src/Flash/Mpp/MPPTaskManager.cpp

printf '%s\n' '--- MPPTaskManager.h gather definitions ---'
sed -n '53,180p' dbms/src/Flash/Mpp/MPPTaskManager.h

printf '%s\n' '--- cancelGather calls ---'
rg -n -C 6 'cancelGather' .

Repository: pingcap/tiflash

Length of output: 32258


Keep the stored grpc::Alarm references owned while cancelling.

std::reference_wrapper does not extend the EstablishCallData lifetime, and MpPTaskManager::abortMPPGather() cancels and erases the wrappers even while the owned EstablishCallData::alarm can still be used by the completion queue. Store the alarms/owner until the alarm is removed, or add an object lifetime handle such that a wrapper can reach the alarm after abortMPPGather() erases it. Run the ComputeServerRunner_testErrorMessage ThreadSanitizer reproduction after resolving the merge conflict.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@dbms/src/Flash/Mpp/MPPTaskManager.h` at line 46, Update the alarms storage in
MPPTaskManager and the abortMPPGather cancellation flow so each grpc::Alarm
remains owned, along with its EstablishCallData owner, until the completion
queue removes the alarm; do not erase a non-owning reference while the alarm may
still be used. Preserve cancellation behavior and run the
ComputeServerRunner_testErrorMessage ThreadSanitizer reproduction after
resolving the merge conflict.

@solotzg solotzg assigned windtalker and unassigned solotzg Aug 10, 2026
@solotzg
solotzg requested review from gengliqi and windtalker August 10, 2026 08:31
@ti-chi-bot

ti-chi-bot Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

@ti-chi-bot: The following tests failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
pull-unit-test cb6c2cb link true /test pull-unit-test
pull-integration-test cb6c2cb link true /test pull-integration-test

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

do-not-merge/cherry-pick-not-approved do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. release-note-none Denotes a PR that doesn't merit a release note. size/S Denotes a PR that changes 10-29 lines, ignoring generated files. type/cherry-pick-for-release-8.5 This PR is cherry-picked to release-8.5 from a source PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants