Cancel reconnect retries during shutdown

This commit is contained in:
Brandon McGinty (chatgpt)
2026-08-10 10:24:38 -04:00
committed by Brandon McGinty
parent e68546eec5
commit 1d6ab79ed0
4 changed files with 51 additions and 5 deletions
+23
View File
@@ -83,6 +83,9 @@ type Barnard struct {
adminBanList gumble.BanList adminBanList gumble.BanList
adminUserList gumble.RegisteredUsers adminUserList gumble.RegisteredUsers
adminACL *gumble.ACL adminACL *gumble.ACL
reconnectStop chan struct{}
reconnectStopOnce sync.Once
} }
// cleanupConnectionAudio releases connection-owned audio resources before a // cleanupConnectionAudio releases connection-owned audio resources before a
@@ -174,6 +177,26 @@ func (b *Barnard) setConnected(connected bool) {
b.stateMutex.Unlock() b.stateMutex.Unlock()
} }
func (b *Barnard) stopReconnects() {
b.reconnectStopOnce.Do(func() {
if b.reconnectStop != nil {
close(b.reconnectStop)
}
})
}
func (b *Barnard) reconnectCanceled() bool {
if b.reconnectStop == nil {
return false
}
select {
case <-b.reconnectStop:
return true
default:
return false
}
}
func (b *Barnard) StopTransmission() { func (b *Barnard) StopTransmission() {
if b.isTransmitting() { if b.isTransmitting() {
b.Notify("micdown", "me", "") b.Notify("micdown", "me", "")
+9 -5
View File
@@ -14,6 +14,7 @@ import (
) )
func (b *Barnard) start() { func (b *Barnard) start() {
b.reconnectStop = make(chan struct{})
b.Config.Attach(gumbleutil.AutoBitrate) b.Config.Attach(gumbleutil.AutoBitrate)
b.Config.Attach(b) b.Config.Attach(b)
b.Config.Address = b.Address b.Config.Address = b.Address
@@ -218,12 +219,15 @@ func (b *Barnard) OnDisconnect(e *gumble.DisconnectEvent) {
} }
func (b *Barnard) reconnectGoroutine() { func (b *Barnard) reconnectGoroutine() {
for { for !b.reconnectCanceled() {
res := b.connect(true) if b.connect(true) {
if res == true { return
break }
select {
case <-b.reconnectStop:
return
case <-time.After(15 * time.Second):
} }
time.Sleep(15 * time.Second)
} }
} }
+17
View File
@@ -193,6 +193,23 @@ func TestCleanupConnectionAudioIsIdempotent(t *testing.T) {
// Tone test mode intentionally does not create an OpenAL stream. Tree // Tone test mode intentionally does not create an OpenAL stream. Tree
// controls must therefore keep local mute state without trying to update one. // controls must therefore keep local mute state without trying to update one.
func TestReconnectCancellationIsSafeBeforeStartup(t *testing.T) {
b := &Barnard{}
b.stopReconnects()
if b.reconnectCanceled() {
t.Fatal("nil reconnect channel should not report cancellation")
}
}
func TestReconnectCancellationStopsWaiters(t *testing.T) {
b := &Barnard{reconnectStop: make(chan struct{})}
b.stopReconnects()
if !b.reconnectCanceled() {
t.Fatal("expected reconnect cancellation")
}
b.stopReconnects() // repeated shutdown must not panic
}
func TestUpdateUserGainAllowsToneTestWithoutStream(t *testing.T) { func TestUpdateUserGainAllowsToneTestWithoutStream(t *testing.T) {
(&Barnard{ToneTest: true}).updateUserGain(&gumble.User{}) (&Barnard{ToneTest: true}).updateUserGain(&gumble.User{})
} }
+2
View File
@@ -393,12 +393,14 @@ func (b *Barnard) OnMicVolumeUp(ui *uiterm.Ui, key uiterm.Key) {
} }
func (b *Barnard) OnQuitPress(ui *uiterm.Ui, key uiterm.Key) { func (b *Barnard) OnQuitPress(ui *uiterm.Ui, key uiterm.Key) {
b.stopReconnects()
b.StopRecordingIfActive(true) b.StopRecordingIfActive(true)
b.Client.Disconnect() b.Client.Disconnect()
b.Ui.Close() b.Ui.Close()
} }
func (b *Barnard) CommandExit(ui *uiterm.Ui, cmd string) { func (b *Barnard) CommandExit(ui *uiterm.Ui, cmd string) {
b.stopReconnects()
b.StopRecordingIfActive(true) b.StopRecordingIfActive(true)
b.Client.Disconnect() b.Client.Disconnect()
b.Ui.Close() b.Ui.Close()