Fix race condition on service stop#201
Conversation
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 0 |
| Duplication | 0 |
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
There was a problem hiding this comment.
Pull request overview
This PR addresses a reported data race during engine shutdown by synchronizing access to shutdown-related state in RuleEngine, and updates CI/build tooling to run tests with the Go race detector.
Changes:
- Protect
syncQueueActiveaccess withstatusMtxinMaybeCallSync()to eliminate the reported race. - Replace the previous shutdown “wait” mechanism with a
mainLoopDonechannel to coordinate Stop() with main loop completion. - Enable
-raceinmake test, and adjust Jenkins build parameters to use a specificwbgo.sobranch.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
wbrules/engine.go |
Adds mainLoopDone and locking around syncQueueActive; changes Stop() waiting logic. |
Makefile |
Runs Go tests with -race enabled. |
Jenkinsfile |
Pins defaultWbGoSoBranch for CI builds. |
debian/changelog |
Bumps package version and notes the race-condition fix. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This reverts commit 359828f.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (2)
wbrules/engine.go:1392
- Stop() stops syncLoop before waiting for mainLoop/handleStop to finish. If mainLoop is still processing buffered events, it can call CallSync(); with syncLoop already stopped and syncStopCh not yet closed (it’s closed in handleStop), CallSync may block sending to syncQueue and prevent handleStop from running, making Stop() wait forever. Consider waiting for handleStop (e.g., via syncStopCh / a wait group) before stopping syncLoop, or closing syncStopCh before terminating syncLoop to ensure CallSync won’t block during shutdown.
engine.eventBuffer.Close()
// stop sync loop
q := make(chan struct{})
engine.syncQuitCh <- q
<-q
for atomic.LoadUint32(&engine.syncQueueActive) == ATOMIC_TRUE {
runtime.Gosched()
}
wbrules/engine.go:1392
- The post-syncLoop wait uses a busy spin with runtime.Gosched(). Since syncStopCh is already closed in handleStop(), Stop() can block on that signal instead of spinning, which avoids unnecessary CPU usage and removes the need for the runtime import.
for atomic.LoadUint32(&engine.syncQueueActive) == ATOMIC_TRUE {
runtime.Gosched()
}
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
| engine.statusMtx.Lock() | ||
| defer engine.statusMtx.Unlock() | ||
| if atomic.LoadUint32(&engine.syncQueueActive) != ATOMIC_TRUE { | ||
| return false | ||
| } |
Что происходит; кому и зачем нужно:
см https://github.com/wirenboard/wbgo-private/pull/90
Что поменялось для пользователей:
ничего
Как проверял/а:
локально