Skip to content

*: refine exit code handling - #68096

Merged
ti-chi-bot[bot] merged 1 commit into
pingcap:masterfrom
ChangRui-Ryan:changrui_cse_exit_code
May 7, 2026
Merged

ti-chi-bot[bot] merged 1 commit into
pingcap:masterfrom
ChangRui-Ryan:changrui_cse_exit_code

Conversation

@ChangRui-Ryan

@ChangRui-Ryan ChangRui-Ryan commented Apr 28, 2026 •

Copy link
Copy Markdown
Contributor

What problem does this PR solve?

Issue Number: ref #67765

Problem Summary:

TiDB handles shutdown signals itself in order to perform graceful shutdown. As a result, when TiDB receives SIGINT, the process can finish cleanup and exit with code 0, which makes an interrupted shutdown indistinguishable from a normal successful exit for scripts, supervisors, or operators checking the process exit status.

SIGINT is conventionally reported as exit code 130 (128 + SIGINT). TiDB should preserve this convention after graceful shutdown, while keeping SIGTERM/SIGHUP/SIGQUIT successful graceful shutdown behavior unchanged.

What changed and how does it work?

This PR passes the received signal into the TiDB shutdown callback. During shutdown, tidb-server records the intended exit code and sets it to 130 when the received signal is SIGINT. Other shutdown signals continue to use the normal successful exit path if cleanup succeeds.

This PR also changes syncLog() to return an error instead of calling os.Exit() internally, so the final exit code is decided in one place in main(). If log sync fails, TiDB exits with code 1; otherwise, SIGINT exits with 130 and normal graceful shutdown exits with 0.

Check List

Tests

  • Unit test
  • Integration test
  • Manual test (add detailed scripts or steps below)
  • No need to test
    • I checked and no code files have been changed.

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

Please refer to Release Notes Language Style Guide to write a quality release note.

None

Summary by CodeRabbit

  • Refactor
    • Shutdown flow now tracks and uses explicit exit codes for signals and ensures logs are flushed before terminating.
  • Bug Fixes
    • Log-sync failures on stdout are treated as non-fatal; other sync errors are reported and can affect the process exit code.
  • Chores
    • Signal handling behavior unified and clarified across platforms, including explicit no-op handling where applicable and a best-effort exit helper.
  • Tests
    • Added unit tests validating exit-code mapping for various signals.

@ti-chi-bot ti-chi-bot Bot added do-not-merge/needs-linked-issue do-not-merge/needs-tests-checked release-note-none Denotes a PR that doesn't merit a release note. size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels Apr 28, 2026
@tiprow

tiprow Bot commented Apr 28, 2026

Copy link
Copy Markdown

Hi @ChangRui-Ryan. Thanks for your PR.

PRs from untrusted users cannot be marked as trusted with /ok-to-test in this repo meaning untrusted PR authors can never trigger tests themselves. Collaborators can still trigger tests on the PR using /test all.

I understand the commands that are listed here.

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.

@coderabbitai

coderabbitai Bot commented Apr 28, 2026 •

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Shutdown handlers now receive the actual os.Signal; main tracks a mutable exitCode (SIGINT maps to an interrupt code), syncLog returns an error instead of calling os.Exit, and main calls os.Exit only when the resulting exit code is non-OK.

Changes

Signal & shutdown

Layer / File(s) Summary
Signal API contract & platform shims
pkg/util/signal/signal_posix.go, pkg/util/signal/signal_wasm.go, pkg/util/signal/signal_windows.go, pkg/util/signal/exit.go
SetupSignalHandler signatures changed to accept os.Signal on POSIX, Windows, and WASM; WASM remains a no-op and now imports os; exit.go added //go:build !windows build tag.
Server main & log sync
cmd/tidb-server/main.go
main maintains exitCode set by the signal handler, adds exitCodeForSignal mapping (SIGINT → interrupt code), refactors syncLog() to return error, calls syncLog() after shutdown, and only calls os.Exit when exit code != OK.
Windows helper
pkg/util/signal/signal_windows.go
Adds exported TiDBExit(sig syscall.Signal) to best-effort signal the current process.
Tests
cmd/tidb-server/main_test.go
Adds TestExitCodeForSignal table-driven test validating exitCodeForSignal for several signals and nil.

Sequence Diagram

sequenceDiagram
    participant OS as Operating System
    participant Handler as Signal Handler
    participant Main as Main
    participant Server as Server/Resources
    participant Logger as syncLog

    OS->>Handler: termination signal (SIGINT/SIGTERM)
    Handler->>Handler: log received signal
    Handler->>Main: shutdownFunc(sig)
    Main->>Main: set exitCode (SIGINT → interrupt code)
    Main->>Server: perform shutdown sequence
    Server-->>Main: shutdown complete
    Main->>Logger: call syncLog()
    Logger->>Logger: fsync logs (ignore /dev/stdout EINVAL)
    Logger-->>Main: return error or nil
    Main->>Main: adjust exitCode based on syncLog result
    Main->>OS: exit with determined exitCode (only if non-OK)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A little bell from kernel lips,
I carry signals on my hips.
I set the code, I save the log,
then gently hop away through fog. 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 57.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title '*: refine exit code handling' accurately summarizes the main change—improving exit code handling in TiDB shutdown, which is the core focus of all file modifications.
Description check ✅ Passed The PR description includes the required sections: Issue Number with 'ref' reference, clear problem summary explaining SIGINT exit code convention, detailed explanation of changes and how they work, and completed checklist with unit tests marked.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 and usage tips.

@codecov

codecov Bot commented Apr 28, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 76.9862%. Comparing base (7940e68) to head (c571849).
⚠️ Report is 28 commits behind head on master.

Additional details and impacted files
@@               Coverage Diff                @@
##             master     #68096        +/-   ##
================================================
- Coverage   77.7489%   76.9862%   -0.7627%     
================================================
  Files          1990       1972        -18     
  Lines        551632     556294      +4662     
================================================
- Hits         428888     428270       -618     
- Misses       121824     127800      +5976     
+ Partials        920        224       -696     
Flag Coverage Δ
integration 41.5418% <100.0000%> (+1.7400%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
dumpling 60.4888% <ø> (ø)
parser ∅ <ø> (∅)
br 50.0597% <ø> (-13.0338%) ⬇️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pkg/util/signal/signal_posix.go (1)

73-85: ⚠️ Potential issue | 🔴 Critical

Keep SetupSignalHandler aligned across all build tags.

The POSIX implementation now takes func(sig os.Signal), but the Windows and WASM implementations have different signatures: Windows uses func() and WASM uses func(bool). This breaks the exported API contract and prevents portable code from using this function across platforms.

All three implementations must be updated to share the same signature:

  • pkg/util/signal/signal_posix.go:74 — func(sig os.Signal)
  • pkg/util/signal/signal_windows.go:31 — func()
  • pkg/util/signal/signal_wasm.go:21 — func(bool)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/util/signal/signal_posix.go` around lines 73 - 85, The exported
SetupSignalHandler signatures are inconsistent across platforms; update the
Windows and WASM implementations to match the POSIX signature
SetupSignalHandler(shutdownFunc func(sig os.Signal)). Edit the
SetupSignalHandler declaration in signal_windows.go and signal_wasm.go to accept
func(sig os.Signal), and update their internal calls to shutdownFunc to pass an
os.Signal value (use nil if no concrete signal is available on that platform) so
the API is portable and caller-compatible with the POSIX implementation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@pkg/util/signal/signal_posix.go`:
- Around line 73-85: The exported SetupSignalHandler signatures are inconsistent
across platforms; update the Windows and WASM implementations to match the POSIX
signature SetupSignalHandler(shutdownFunc func(sig os.Signal)). Edit the
SetupSignalHandler declaration in signal_windows.go and signal_wasm.go to accept
func(sig os.Signal), and update their internal calls to shutdownFunc to pass an
os.Signal value (use nil if no concrete signal is available on that platform) so
the API is portable and caller-compatible with the POSIX implementation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 2d697f19-98d7-4ce6-a42c-63e368a1817d

📥 Commits

Reviewing files that changed from the base of the PR and between a46bec4 and 687c0dd.

📒 Files selected for processing (2)
  • cmd/tidb-server/main.go
  • pkg/util/signal/signal_posix.go

@lance6716

Copy link
Copy Markdown
Contributor

I think it breaks backward compatibility. For example, some user scripts may have rely on the error code. Please check with PM about this change?

@ChangRui-Ryan
ChangRui-Ryan force-pushed the changrui_cse_exit_code branch from 687c0dd to 596f50e Compare April 29, 2026 08:42

@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: 1

🧹 Nitpick comments (2)
pkg/util/signal/signal_wasm.go (1)

22-24: Document that this handler is intentionally a no-op on WASM.

SetupSignalHandler is exported, but this implementation never invokes the callback. A short doc comment calling out the WASM no-op behavior would make the platform contract much clearer for callers.

As per coding guidelines, "Comments SHOULD explain non-obvious intent, constraints, invariants, concurrency guarantees, SQL/compatibility contracts, or important performance trade-offs" and "Keep exported-symbol doc comments, and prefer semantic constraints over name restatement."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/util/signal/signal_wasm.go` around lines 22 - 24, Add an explanatory doc
comment to the exported SetupSignalHandler function indicating that on WASM this
implementation is intentionally a no-op and will not invoke the provided
shutdownFunc callback; update the comment above SetupSignalHandler to state the
platform constraint and the expected behavior callers should rely on so it's
clear why the function body is empty.
cmd/tidb-server/main.go (1)

149-153: Explain the 130 convention inline.

exitCodeInt reads like a magic number unless the reader already knows the shell convention. A brief note like 128 + SIGINT would make the intent obvious during future refactors.

As per coding guidelines, "Code SHOULD be self-documenting through clear naming and structure" and "Comments SHOULD explain non-obvious intent, constraints, invariants, concurrency guarantees, SQL/compatibility contracts, or important performance trade-offs."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmd/tidb-server/main.go` around lines 149 - 153, Add an inline explanation
for the magic number used by exitCodeInt so readers know it represents a
signal-based exit (130 == 128 + SIGINT); update the const block for exitCodeInt
to include a brief comment like "130 == 128 + SIGINT" and optionally compute it
from syscall.SIGINT (e.g., 128 + int(syscall.SIGINT)) using the exitCodeInt
symbol to avoid the magic number and make intent explicit.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/util/signal/signal_windows.go`:
- Around line 47-57: TiDBExit currently swallows failures on Windows because
os.Process.Signal only supports os.Kill; change TiDBExit to return an error
instead of hiding it and explicitly handle unsupported signals on Windows: in
TiDBExit, after os.FindProcess, detect if sig is not syscall.SIGKILL (or
os.Kill) and return a clear error (e.g., fmt.Errorf("signal %v not supported on
Windows", sig)) rather than just logging, and update callers to handle the
returned error; reference the TiDBExit function, os.FindProcess, and p.Signal
when making these changes.

---

Nitpick comments:
In `@cmd/tidb-server/main.go`:
- Around line 149-153: Add an inline explanation for the magic number used by
exitCodeInt so readers know it represents a signal-based exit (130 == 128 +
SIGINT); update the const block for exitCodeInt to include a brief comment like
"130 == 128 + SIGINT" and optionally compute it from syscall.SIGINT (e.g., 128 +
int(syscall.SIGINT)) using the exitCodeInt symbol to avoid the magic number and
make intent explicit.

In `@pkg/util/signal/signal_wasm.go`:
- Around line 22-24: Add an explanatory doc comment to the exported
SetupSignalHandler function indicating that on WASM this implementation is
intentionally a no-op and will not invoke the provided shutdownFunc callback;
update the comment above SetupSignalHandler to state the platform constraint and
the expected behavior callers should rely on so it's clear why the function body
is empty.
🪄 Autofix (Beta)

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

Run ID: 14701fe4-936a-4c28-96ae-ca564b2b40f3

📥 Commits

Reviewing files that changed from the base of the PR and between 687c0dd and 596f50e.

📒 Files selected for processing (5)
  • cmd/tidb-server/main.go
  • pkg/util/signal/exit.go
  • pkg/util/signal/signal_posix.go
  • pkg/util/signal/signal_wasm.go
  • pkg/util/signal/signal_windows.go
✅ Files skipped from review due to trivial changes (1)
  • pkg/util/signal/exit.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/util/signal/signal_posix.go

Comment on lines +47 to +57
// TiDBExit sends a signal to the current process.
func TiDBExit(sig syscall.Signal) {
p, err := os.FindProcess(os.Getpid())
if err != nil {
logutil.BgLogger().Error("failed to find current process", zap.Error(err), zap.Stringer("signal", sig))
return
}
if err := p.Signal(sig); err != nil {
logutil.BgLogger().Error("failed to send signal", zap.Error(err), zap.Stringer("signal", sig))
}
}

@coderabbitai coderabbitai Bot Apr 29, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

In the current Go documentation for Windows, does os.Process.Signal support delivering syscall.SIGINT or syscall.SIGTERM to the current process? Please cite the relevant os.Process.Signal / os.Interrupt documentation and Windows-specific caveats.

💡 Result:

No, in the current Go documentation for Windows, os.Process.Signal does not support delivering syscall.SIGINT or syscall.SIGTERM to the current process (or any process). It only supports os.Kill, which forces termination without graceful handling. Sending os.Interrupt (equivalent to SIGINT) is explicitly not implemented on Windows and returns an error. The os package documentation for Process.Signal states: "The only signal values guaranteed to be present in the os package on all systems are os.Interrupt (send the process an interrupt) and os.Kill (force the process to exit). On Windows, sending os.Interrupt to a process with os.Process.Signal is not implemented; it will return an error instead of sending a signal." (cited from multiple GitHub issues #46345, #6720, #27854 quoting the docs, and StackOverflow answers referencing it). syscall.SIGINT and syscall.SIGTERM exist as constants on Windows (SIGINT=2, SIGTERM=15), but os.Process.Signal does not support arbitrary syscall.Signal values on Windows; it only handles Kill and would return EWINDOWS for others. Windows-specific caveats: Windows lacks Unix-style signals. os.Interrupt can be received via os/signal.Notify (e.g., Ctrl+C maps to os.Interrupt), but cannot be sent programmatically to a specific process via Process.Signal due to API limitations (GenerateConsoleCtrlEvent sends to console process groups, not individual processes, and only for attached console processes created with specific flags). Issues #6720 and #46345 discuss this in detail, closed as impossible without changing semantics. For child processes from exec.Cmd, if not in the same console group, it won't work reliably. os/signal.NotifyContext documentation notes os.Interrupt reception on Windows but does not claim sending support. No changes noted up to Go 1.25.6 or recent issues as of 2026.

Citations:


TiDBExit silently fails on Windows for non-Kill signals.

On Windows, os.Process.Signal() does not support Unix-style signals like syscall.SIGINT or syscall.SIGTERM—it only supports os.Kill. Per Go's os package documentation and GitHub issues #46345 and #6720, sending os.Interrupt via Process.Signal returns an error on Windows instead of delivering the signal. This function logs the error and returns, leaving the process running despite the expectation of a signal handler effect. Either document the Windows limitation explicitly, return an error to the caller, or implement platform-appropriate shutdown logic.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/util/signal/signal_windows.go` around lines 47 - 57, TiDBExit currently
swallows failures on Windows because os.Process.Signal only supports os.Kill;
change TiDBExit to return an error instead of hiding it and explicitly handle
unsupported signals on Windows: in TiDBExit, after os.FindProcess, detect if sig
is not syscall.SIGKILL (or os.Kill) and return a clear error (e.g.,
fmt.Errorf("signal %v not supported on Windows", sig)) rather than just logging,
and update callers to handle the returned error; reference the TiDBExit
function, os.FindProcess, and p.Signal when making these changes.

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.

IMHO it is fine since TiDB is rarely deployed(not officially supported) on Windows.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@bb7133, understood — that's a fair point. Since TiDB is not officially supported on Windows, the best-effort semantics of TiDBExit are acceptable there. I'll note this for future reviews.


✏️ Learnings added
Learnt from: bb7133
Repo: pingcap/tidb PR: 68096
File: pkg/util/signal/signal_windows.go:47-55
Timestamp: 2026-05-06T06:23:01.302Z
Learning: TiDB is rarely deployed and not officially supported on Windows. Windows-specific limitations (e.g., os.Process.Signal not supporting Unix-style signals like SIGINT/SIGTERM) are acceptable in pkg/util/signal/signal_windows.go since Windows is not an officially supported deployment target for TiDB.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: joechenrh
Repo: pingcap/tidb PR: 66878
File: pkg/planner/core/logical_plan_builder.go:6455-6472
Timestamp: 2026-03-11T06:29:00.122Z
Learning: Ensure code reviews verify the VirtualAssignmentsOffset semantics: the planner sets Update.VirtualAssignmentsOffset = len(update.List). The executor should only apply OrderedList[:VirtualAssignmentsOffset] when composing new rows, and only after the 'changed' check should it group/evaluate OrderedList[VirtualAssignmentsOffset:] per table. This pattern applies to files under pkg/planner/core and pkg/executor (e.g., common_plans.go and update.go). Reviewers should check that updates respect slicing behavior, that the offset is consistently derived from the planner, and that downstream code does not bypass the offset when creating new rows. Add tests validating both branches: the slice before the offset for new rows, and the per-table handling of the slice after the offset.

@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.

🧹 Nitpick comments (1)
cmd/tidb-server/main.go (1)

428-433: Consider documenting exit-code precedence in-line.

At Line 428–Line 430, syncLog() failure overwrites a prior SIGINT code (130) with 1. A brief comment here would make this contract obvious to future maintainers.

Suggested inline clarification
 	<-exited
+	// Exit-code precedence:
+	// 1) log sync failure -> 1
+	// 2) otherwise keep signal-derived code (e.g. SIGINT -> 130)
 	if err := syncLog(); err != nil {
 		exitCode = exitCodeErr
 	}

As per coding guidelines "Comments SHOULD explain non-obvious intent, constraints, invariants, concurrency guarantees, SQL/compatibility contracts, or important performance trade-offs, and SHOULD NOT restate what the code already makes clear."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmd/tidb-server/main.go` around lines 428 - 433, Add a short inline comment
explaining exit-code precedence: when syncLog() returns an error it sets
exitCode = exitCodeErr (overriding any prior signal-derived value such as
SIGINT/130), and then the later check if exitCode != exitCodeOK causes
os.Exit(exitCode); update the block around syncLog(), exitCode, exitCodeErr,
exitCodeOK to include this clarification so future maintainers understand that
syncLog() failures take precedence over earlier signal codes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@cmd/tidb-server/main.go`:
- Around line 428-433: Add a short inline comment explaining exit-code
precedence: when syncLog() returns an error it sets exitCode = exitCodeErr
(overriding any prior signal-derived value such as SIGINT/130), and then the
later check if exitCode != exitCodeOK causes os.Exit(exitCode); update the block
around syncLog(), exitCode, exitCodeErr, exitCodeOK to include this
clarification so future maintainers understand that syncLog() failures take
precedence over earlier signal codes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: b1bbcdf9-ef85-47af-8efc-add3767b55d2

📥 Commits

Reviewing files that changed from the base of the PR and between 596f50e and 5a4ff81.

📒 Files selected for processing (3)
  • cmd/tidb-server/main.go
  • pkg/util/signal/signal_wasm.go
  • pkg/util/signal/signal_windows.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • pkg/util/signal/signal_windows.go
  • pkg/util/signal/signal_wasm.go

@ChangRui-Ryan
ChangRui-Ryan force-pushed the changrui_cse_exit_code branch from 5a4ff81 to fec3785 Compare April 29, 2026 10:11
@ChangRui-Ryan

Copy link
Copy Markdown
Contributor Author

I think it breaks backward compatibility. For example, some user scripts may have rely on the error code. Please check with PM about this change?

Thanks for raising this.

I think the compatibility impact should be acceptable here.

Before this change, these abnormal shutdown paths did not expose useful information through the process exit status. Whether TiDB was interrupted by a signal or hit an error during shutdown, the observable exit code could still be 0, which made the exit status effectively meaningless for deployment systems and scripts.

This PR keeps the normal successful exit path returning 0, and only makes selected abnormal termination paths return a non-zero code. For example, SIGINT returns 128 + SIGINT = 130, following the common POSIX convention.

So if a user previously checked the exit code, they could not distinguish these abnormal cases anyway. The new behavior gives them more accurate information instead of preserving an indistinguishable 0 for every case.

@ChangRui-Ryan

Copy link
Copy Markdown
Contributor Author

/retest

@tiprow

tiprow Bot commented Apr 29, 2026

Copy link
Copy Markdown

@ChangRui-Ryan: PRs from untrusted users cannot be marked as trusted with /ok-to-test in this repo meaning untrusted PR authors can never trigger tests themselves. Collaborators can still trigger tests on the PR using /test.

Details

In response to this:

/retest

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.

@ChangRui-Ryan

Copy link
Copy Markdown
Contributor Author

/retest

@tiprow

tiprow Bot commented Apr 30, 2026

Copy link
Copy Markdown

@ChangRui-Ryan: PRs from untrusted users cannot be marked as trusted with /ok-to-test in this repo meaning untrusted PR authors can never trigger tests themselves. Collaborators can still trigger tests on the PR using /test.

Details

In response to this:

/retest

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.

@ChangRui-Ryan

Copy link
Copy Markdown
Contributor Author

/retest

@tiprow

tiprow Bot commented Apr 30, 2026

Copy link
Copy Markdown

@ChangRui-Ryan: PRs from untrusted users cannot be marked as trusted with /ok-to-test in this repo meaning untrusted PR authors can never trigger tests themselves. Collaborators can still trigger tests on the PR using /test.

Details

In response to this:

/retest

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.

Comment thread cmd/tidb-server/main.go
<-exited
syncLog()
if err := syncLog(); err != nil {
exitCode = exitCodeErr

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.

This looks reasonable to me...but how about adding a comment here for this?

@bb7133 bb7133 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

@ti-chi-bot ti-chi-bot Bot added approved needs-1-more-lgtm Indicates a PR needs 1 more LGTM. labels May 6, 2026
@ti-chi-bot

ti-chi-bot Bot commented May 6, 2026

Copy link
Copy Markdown

@iosmanthus: adding LGTM is restricted to approvers and reviewers in OWNERS files.

Details

In response to this:

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.

@ChangRui-Ryan
ChangRui-Ryan force-pushed the changrui_cse_exit_code branch from fec3785 to a50e843 Compare May 7, 2026 11:29
@ChangRui-Ryan
ChangRui-Ryan force-pushed the changrui_cse_exit_code branch from a50e843 to c571849 Compare May 7, 2026 11:39

@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.

🧹 Nitpick comments (1)
pkg/util/signal/signal_windows.go (1)

47-55: ⚡ Quick win

Log the FindProcess error before silently returning.

The p.Signal error is intentionally discarded and explained by the "best effort" comment, but the FindProcess error path is a silent no-op with no trace. On the rare occasion FindProcess fails, there is no observable evidence and the caller has no way to detect that no signal was delivered. A single log line would make post-mortem debugging possible without changing behaviour.

♻️ Proposed fix
 func TiDBExit(sig syscall.Signal) {
 	p, err := os.FindProcess(os.Getpid())
 	if err != nil {
+		logutil.BgLogger().Error("TiDBExit: failed to find current process", zap.Error(err))
 		return
 	}
 	// Best effort; Windows does not support POSIX signal shutdown semantics.
 	_ = p.Signal(sig)
 }
🤖 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 `@pkg/util/signal/signal_windows.go` around lines 47 - 55, TiDBExit currently
silently returns if os.FindProcess(os.Getpid()) fails; change it to log the
error before returning so failures are observable. In the TiDBExit function,
after the os.FindProcess(...) call, if err != nil then emit a single log entry
including the error (e.g., "FindProcess failed" + err) using the package's
logger or log.Printf, then return; keep the rest of the function (the
best-effort call to p.Signal) unchanged.
🤖 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.

Nitpick comments:
In `@pkg/util/signal/signal_windows.go`:
- Around line 47-55: TiDBExit currently silently returns if
os.FindProcess(os.Getpid()) fails; change it to log the error before returning
so failures are observable. In the TiDBExit function, after the
os.FindProcess(...) call, if err != nil then emit a single log entry including
the error (e.g., "FindProcess failed" + err) using the package's logger or
log.Printf, then return; keep the rest of the function (the best-effort call to
p.Signal) unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 3e5af844-bd36-40e7-8403-e4637c8065b8

📥 Commits

Reviewing files that changed from the base of the PR and between fec3785 and a50e843.

📒 Files selected for processing (6)
  • cmd/tidb-server/main.go
  • cmd/tidb-server/main_test.go
  • pkg/util/signal/exit.go
  • pkg/util/signal/signal_posix.go
  • pkg/util/signal/signal_wasm.go
  • pkg/util/signal/signal_windows.go
✅ Files skipped from review due to trivial changes (1)
  • pkg/util/signal/exit.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • pkg/util/signal/signal_posix.go
  • pkg/util/signal/signal_wasm.go
  • cmd/tidb-server/main.go

@ti-chi-bot

ti-chi-bot Bot commented May 7, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: bb7133, iosmanthus, wjhuang2016

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

The pull request process is described 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

@ti-chi-bot ti-chi-bot Bot added lgtm and removed needs-1-more-lgtm Indicates a PR needs 1 more LGTM. labels May 7, 2026
@ti-chi-bot

ti-chi-bot Bot commented May 7, 2026

Copy link
Copy Markdown

[LGTM Timeline notifier]

Timeline:

  • 2026-05-06 06:27:05.420749141 +0000 UTC m=+249098.294099103: ☑️ agreed by bb7133.
  • 2026-05-07 11:43:23.665494574 +0000 UTC m=+354476.538844546: ☑️ agreed by wjhuang2016.

@ti-chi-bot
ti-chi-bot Bot merged commit f3d6cea into pingcap:master May 7, 2026
35 checks passed
ti-chi-bot pushed a commit that referenced this pull request May 8, 2026
yongman pushed a commit to yongman/tidb that referenced this pull request Jun 3, 2026
takaidohigasi added a commit to takaidohigasi/tidb that referenced this pull request Aug 21, 2026
Resolve conflicts against ~3.5 months of master drift:

- pkg/util/codec, pkg/tablecodec: rebase the DESC-aware encoding onto the
  explicit-collation Encoder introduced by pingcap#69566. EncodeKeyWithDesc
  becomes an Encoder method (with the package-level wrapper kept for
  range/probe-key callers), and GenIndexKey dispatches through the
  caller-supplied encoder on both the ASC fast path and the DESC path.
- pkg/executor: thread indexColDescFlags through the refactored
  buildKeyRanges signature (new rangeMemTracker) and the new unified
  IndexMergeReaderExecutor.buildPartialWorkerKVRanges.
- Resolve files touched only by interim cherry-picks (pingcap#68096, pingcap#68137,
  pingcap#68148, pingcap#68168) to their canonical upstream versions.
- BUILD.bazel: union of dependency edits; adopt upstream shard_count.

Verified with go vet + unit tests on all touched packages, the pkg/ddl
DESC feature tests (-tags=intest), and a full bazel CI build.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: takaidohigasi <takaidohigasi@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved lgtm release-note-none Denotes a PR that doesn't merit a release note. size/M Denotes a PR that changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants