apache / apache/dubbo-go

[Bug] go test -race exposes 10 data races (8 packages)

Open
#3,614 5 comments 0 reactions 1 assignee Claimed by @lizining1231 View on GitHub
☢️ Bug 3.3.3
Dominant language
Go
Stars
5k
Forks
1k
Avg merge
2d 8h
Merged PRs (30d)
31

Description

### Summary

Running go test -race ./... fails 10 tests across 8 packages due to Data Race.

This issue categorizes the failures by reproducibility and lists the failing test locations, related source locations, and initial analysis, all for evaluating fixes or marking them as known issues.

### Affected Locations

#### 1. Stable data races (reproducible both in a full-suite run and in per-package runs)

| Package | Test | Test Location | Related Source Location |
| -------------------------------------------- | --------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
| 1. `cluster/cluster/failback` | `TestFailbackRetryFailed` | [cluster\_test.go L136-L180](https://github.com/apache/dubbo-go/blob/master/cluster/cluster/failback/cluster_test.go#L136-L180) | Read [cluster\_invoker.go L109](https://github.com/apache/dubbo-go/blob/master/cluster/cluster/failback/cluster_invoker.go#L109) (`process` reads `lastT`) vs Write [cluster\_invoker.go L198-L212](https://github.com/apache/dubbo-go/blob/master/cluster/cluster/failback/cluster_invoker.go#L198-L212) (`checkRetry` writes `lastT`/`nextBackoff`) |
| 2. `cluster/cluster/failback` | `TestFailbackOutOfLimit` | [cluster\_test.go L231-L263](https://github.com/apache/dubbo-go/blob/master/cluster/cluster/failback/cluster_test.go#L231-L263) | Write [cluster\_invoker.go L95](https://github.com/apache/dubbo-go/blob/master/cluster/cluster/failback/cluster_invoker.go#L95) (`process` creates `ticker`) vs Read [cluster\_invoker.go L173](https://github.com/apache/dubbo-go/blob/master/cluster/cluster/failback/cluster_invoker.go#L173) (`Destroy` calls `ticker.Stop`) |
| 3. `cluster/router/chain` | `TestRouteCacheGenerationRace` | [chain\_test.go L423-L474](https://github.com/apache/dubbo-go/blob/master/cluster/router/chain/chain_test.go#L423-L474) | Write [chain\_test.go L386](https://github.com/apache/dubbo-go/blob/master/cluster/router/chain/chain_test.go#L386) (`SetCache` writes `r.cache`) vs Read [chain\_test.go L401](https://github.com/apache/dubbo-go/blob/master/cluster/router/chain/chain_test.go#L401) (`Route` reads `r.cache`) |
| 4. `config_center/apollo` | `TestListener` | [impl\_test.go L257-L288](https://github.com/apache/dubbo-go/blob/master/config_center/apollo/impl_test.go#L257-L288) | Map iteration [listener.go L56](https://github.com/apache/dubbo-go/blob/master/config_center/apollo/listener.go#L56) vs Write [listener.go L68](https://github.com/apache/dubbo-go/blob/master/config_center/apollo/listener.go#L68)/[L74](https://github.com/apache/dubbo-go/blob/master/config_center/apollo/listener.go#L74); also the test's own global variable [impl\_test.go L98](https://github.com/apache/dubbo-go/blob/master/config_center/apollo/impl_test.go#L98) (reads `mockConfigRes`) vs [L261](https://github.com/apache/dubbo-go/blob/master/config_center/apollo/impl_test.go#L261) (writes `mockConfigRes`), and [L300-L302](https://github.com/apache/dubbo-go/blob/master/config_center/apollo/impl_test.go#L300-L302) (`Process` writes `event`/`count`) vs [L273-L274](https://github.com/apache/dubbo-go/blob/master/config_center/apollo/impl_test.go#L273-L274) (the test reads) |
| 5. `protocol/dubbo` | `TestDubboProtocol_Refer` | [dubbo\_protocol\_test.go L129-L152](https://github.com/apache/dubbo-go/blob/master/protocol/dubbo/dubbo_protocol_test.go#L129-L152) | Third-party `dubbo-getty v1.4.10`: [session.go L857](https://github.com/apache/dubbo-getty/blob/v1.4.10/session.go#L857) (`s.ReadTimeout()`) vs [connection.go L277-L278](https://github.com/apache/dubbo-getty/blob/v1.4.10/connection.go#L277-L278) (`SetReadDeadline`/`Store`) |
| 6. `protocol/grpc` | `TestGrpcHealthWatchEmitsClosingEvent` | [active\_notify\_test.go L88-L139](https://github.com/apache/dubbo-go/blob/master/protocol/grpc/active_notify_test.go#L88-L139) | Write [active\_notify\_test.go L51](https://github.com/apache/dubbo-go/blob/master/protocol/grpc/active_notify_test.go#L51) (callback goroutine `append events`) vs Read [active\_notify\_test.go L133](https://github.com/apache/dubbo-go/blob/master/protocol/grpc/active_notify_test.go#L133) (test goroutine `len(events)`) |
| `registry/servicediscovery` (unnumbered) | `TestServiceDiscoveryRegistryUnRegister_Concurrent` | [service\_discovery\_registry\_test.go L1307-L1371](https://github.com/apache/dubbo-go/blob/master/registry/servicediscovery/service_discovery_registry_test.go#L1307-L1371) | [service\_discovery\_registry\_test.go L1368](https://github.com/apache/dubbo-go/blob/master/registry/servicediscovery/service_discovery_registry_test.go#L1368) lock-free `append(sdReg.instances, ...)`. Note: the test intentionally omits locking to simulate a real concurrent scenario, and the race is the expected outcome of the test. |
| 7. `server` | `TestCfgAPI_Export` | [inst\_test.go L85-L90](https://github.com/apache/dubbo-go/blob/master/server/inst_test.go#L85-L90) | Write [server.go L200](https://github.com/apache/dubbo-go/blob/master/protocol/triple/triple_protocol/server.go#L200) (`startHttp2` assigns `s.httpSrv`) vs Read [server.go L326](https://github.com/apache/dubbo-go/blob/master/protocol/triple/triple_protocol/server.go#L326) (`GracefulStop` reads `s.httpSrv`) |

#### 2. Non-deterministic data races (unstable reproduction: intermittent on a single run, always reproducible with `-count=N`)

| Package | Test | Test Location | Related Source Location |
| ------------------ | --------------------- | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
| 8. `server` | `TestCfgAPI_Call` | https://github.com/apache/dubbo-go/blob/master/server/inst_test.go#L94-L100 | Same as `TestCfgAPI_Export`: https://github.com/apache/dubbo-go/blob/master/protocol/triple/triple_protocol/server.go#L200 vs https://github.com/apache/dubbo-go/blob/master/protocol/triple/triple_protocol/server.go#L326 (passes on a single `-run`, race reproduces with `-count=3`) |
| 9. `remoting/getty` | `TestTCPPackageHandle` | https://github.com/apache/dubbo-go/blob/master/remoting/getty/readwriter_test.go#L45-L50 | Read https://github.com/apache/dubbo-go/blob/master/remoting/getty/readwriter.go#L128 (`Write` reads global `srvConf`) vs Write https://github.com/apache/dubbo-go/blob/master/remoting/getty/getty_server.go#L116-L117 (`SetServerConfig` writes `srvConf`). Always reported in full-suite runs, intermittent when run alone |
| 10. `common/config` | `TestNewRegistryDirectoryConsumerListenerUsesResolvedApplicationName` | https://github.com/apache/dubbo-go/blob/master/registry/directory/directory_test.go#L191-L198 | Write https://github.com/apache/dubbo-go/blob/master/common/config/environment.go#L100 (`SetDynamicConfiguration`) vs Read https://github.com/apache/dubbo-go/blob/master/common/config/environment.go#L105 (`GetDynamicConfiguration`). Cross-test race: the reader goroutine is a `MockRegistry.

### Suggested Fixes

Detailed solutions for each issue will be submitted in separate issues; this issue only lists the scope of the fixes.

### Verification

These tests are skipped via -skip in CI. To reproduce locally, remove the corresponding tests from -skip and run:

```bash
GOTOOLCHAIN=go1.25.0 go test -race -count=1 ./...
```

Category 1 (stable) appears on a single run;
for Category 2 (unstable), use `-count=N` to increase the hit rate.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.