upstream auto-manager races manual 'upstream connect' — counter-switches back to a disabled section mid-join
Maintainers usually reply within 1 day
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 48/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Active
- Tech stack
- go
- Domain
- backend, networking
Research direction
Start in src/cli/server.go at handleUpstreamConnectStreaming and trace how it calls SwitchUpstream and PauseConnectivityChecks; then inspect the manager’s periodic connectivity tick. Reproduce the race described in the issue with a manual connect that waits for DHCP while a tick fires. Done means the manager cannot counter-switch during the manual join and the behavior is covered for completion and failure paths.
Written by the indexing model from the issue text.
Description
Summary
The upstream connectivity manager's periodic tick can fire during a manual tollgate upstream connect's DHCP wait and switch the radio to a different section — in the measured case, back to the stale foreign section the connect flow had just disabled — re-enabling it and preventing the join from ever completing.
Evidence (bench, 2026-10-11)
From the #817/#848 gate-run session (Pi 4 / brcmfmac / single radio; logread timeline):
08:20:41 tollgate-wrt: Creating new named STA interface interface=upstream_2 ssid=2
08:20:41 tollgate-wrt: Switching upstream active=tollgate_uplink candidate=upstream_2 ssid=2
08:21:08 tollgate-wrt: Switching upstream active=upstream_2 candidate=tollgate_uplink ssid=2
08:23:42 tollgate-wrt: WARN Timed out waiting for DHCP, reverting to previous upstream candidate=upstream_2 ssid=2
The manual flow disabled tollgate_uplink (its competitor sweep, #848) and enabled upstream_2; 27 seconds later — one 30 s connectivity tick (upstream_wifi.fast_check_seconds) — the auto-manager observed the transient loss, picked the known candidate tollgate_uplink, and switched to it (its own switch path re-enables its candidate). The join never had a stable radio after that.
Root cause
handleUpstreamConnectStreaming pauses the manager only after success — src/cli/server.go calls s.upstreamManager.PauseConnectivityChecks(s.manualPauseDuration()) after SwitchUpstream returns nil. During the switch window — up to dhcp_timeout_seconds (default 180 s) — the manager is live, and with a 30 s tick it is essentially guaranteed to fire mid-join whenever the churn reads as a connectivity loss.
Interaction with #848: the manager's counter-switch re-enables exactly the section the competitor sweep disabled, so this race can undo those guarantees on single-radio devices.
Repro / workaround
Any manual connect on a radio where the tick observes the churn. Bench workaround used during the gate run: park the tick first ("fast_check_seconds" and "scan_interval_seconds" set large in the service config, then restart).
Suggested fix shape
Either pause the connectivity checks for the manual-pause window before the switch starts (the handler already computes the duration — move the pause ahead of the SwitchUpstream call and unpause on completion/failure), or make the manager decline to act on radios with an in-flight manual switch. Either way, the connect flow and the manager must not both drive the radio.
- Dominant language
- Go
- Stars
- 12
- Forks
- 14
- Avg merge
- 1d 6h
- Merged PRs (30d)
- 235
Getting set up
- No Dockerfile or Docker Compose file
- No pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from OpenTollGate/tollgate-module-basic-go
-
Session event emits the customer's MAC address in the p tag — spec-invalid value on every payment responsePossibly taken A pull request linked to this issue is open or already merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
OpenTollGate/tollgate-module-basic-go#949 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
OpenTollGate/tollgate-module-basic-go#833 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
OpenTollGate/tollgate-module-basic-go#813 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
OpenTollGate/tollgate-module-basic-go#804 ·
Maintainers usually reply within 1 day
-
go-battery needs an ndsctl on PATH: TestPurchaseSessionGuardHoldsThroughTheOutcomeUnknownWindow fails on bare hosts (passes with stub)Possibly taken @Amperstrand claimed this 5 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
OpenTollGate/tollgate-module-basic-go#726 · 2 comments ·
Maintainers usually reply within 1 day
All issues in OpenTollGate/tollgate-module-basic-go
Similar issues
-
documentation hacktoberfest priority: low skill: good first issue status: ready for dev
Difficulty 2/5 Half a day Newbie friendliness 85/100
hyperledger-labs/fabric-smart-client#2142 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
numberly/vault-db-injector#107 ·
Maintainers usually reply within 1 day
-
area/import kind/bug
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
Maintainers usually reply within 1 day
-
[DOC] Wrong sg_egress_ports range in the Terraform Databricks Guide for AWS Hub & Spoke with Network FirewallPossibly taken @akhil9tiet claimed this today. Opendocs
Difficulty 1/5 Under an hour Newbie friendliness 72/100
databricks/terraform-provider-databricks#6080 · 1 comment ·
Maintainers usually reply within 3 days
-
spqr-coordinator usage shows 'run --config', but 'run' is not a subcommand (unknown command "run")Open
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
pg-sharding/spqr#3092 · 1 comment ·
Maintainers usually reply within 1 day