data-race: ProcessInfo.ToRow() reads StmtCtx without RefCountOfStmtCtx protection
- Dominant language
- Go
- Stars
- 40.5k
- Forks
- 6.2k
- PR merge metrics
- PR metrics pending
Description
## Bug Report
### Description
`ProcessInfo.ToRow()` reads `pi.StmtCtx` fields (such as `MemTracker`, `AffectedRows`) without using the `RefCountOfStmtCtx` protection mechanism. Meanwhile, the session goroutine can concurrently reset the same `StatementContext` via `InitStatementContext()` → `StatementContext.Reset()` or `InitMemTracker()`.
This causes a data race detected by the Go race detector.
### Race Pattern
- **WRITE** (session goroutine): `executeStmtImpl()` → `ResetContextOfStmt()` → `InitStatementContext()` → `StatementContext.Reset()` or `InitMemTracker()` — writes to a `StatementContext` object.
- **READ** (background goroutine): `servermemorylimit.Handle.Run()` → `killSessIfNeeded()` → `recordOne()` → `info.ToRow()` — reads `pi.StmtCtx.MemTracker`, `pi.StmtCtx.AffectedRows()` from the same `StatementContext`.
### Root Cause
The existing `RefCountOfStmtCtx` mechanism (`TryIncrease()/Decrease()`) is designed to protect concurrent access to `StmtCtx`. `GenLogFields()` in `pkg/util/util.go` correctly uses this protection, but `ToRow()` does not.
### Reproduction
Seen in CI for `TestGlobalMemoryControlForPrepareAnalyze` with race detector enabled. The test spawns a background goroutine running `servermemorylimit.Handle.Run()` while executing ANALYZE statements.
### Fix
Add `RefCountOfStmtCtx` protection in `ProcessInfo.ToRow()`, following the same pattern used by `GenLogFields()`. If `TryIncrease` fails (the StmtCtx is being frozen/reset), skip the StmtCtx-dependent fields.
### Example Race Log
```
WARNING: DATA RACE
Write at 0x00c006d14d88 by goroutine 62:
github.com/pingcap/tidb/pkg/sessionctx/stmtctx.(*StatementContext).InitMemTracker()
pkg/sessionctx/stmtctx/stmtctx.go:976 +0x1031
github.com/pingcap/tidb/pkg/executor.ResetContextOfStmt()
pkg/executor/select.go:1014 +0x1002
Previous read at 0x00c006d14d88 by goroutine 11384:
github.com/pingcap/tidb/pkg/session/sessmgr.(*ProcessInfo).ToRow()
pkg/session/sessmgr/processinfo.go:146 +0x108
github.com/pingcap/tidb/pkg/util/servermemorylimit.recordOne()
pkg/util/servermemorylimit/servermemorylimit.go:224 +0xec
github.com/pingcap/tidb/pkg/util/servermemorylimit.killSessIfNeeded()
pkg/util/servermemorylimit/servermemorylimit.go:184 +0x15e4
```
### Affected Files
- `pkg/session/sessmgr/processinfo.go` — `ToRow()` method
- `pkg/util/servermemorylimit/servermemorylimit.go` — caller `recordOne()`
- `pkg/executor/infoschema_reader.go` — another caller of `ToRow()` without protection
Contributor guide
Assessment
This issue has not been assessed yet.