forked from Silverfish/proton-bridge
Other: Fix goroutine leak in OnStatusDown
We should spawn the goroutine as a bridge async task rather than as a normal goroutine
This commit is contained in:
@ -271,10 +271,12 @@ func (bridge *Bridge) init(tlsReporter TLSReporter) error {
|
||||
bridge.api.AddStatusObserver(func(status liteapi.Status) {
|
||||
switch {
|
||||
case status == liteapi.StatusUp:
|
||||
go bridge.onStatusUp()
|
||||
bridge.publish(events.ConnStatusUp{})
|
||||
bridge.tasks.Once(bridge.onStatusUp)
|
||||
|
||||
case status == liteapi.StatusDown:
|
||||
go bridge.onStatusDown()
|
||||
bridge.publish(events.ConnStatusDown{})
|
||||
bridge.tasks.Once(bridge.onStatusDown)
|
||||
}
|
||||
})
|
||||
|
||||
@ -429,48 +431,36 @@ func (bridge *Bridge) remWatcher(watcher *watcher.Watcher[events.Event]) {
|
||||
watcher.Close()
|
||||
}
|
||||
|
||||
func (bridge *Bridge) onStatusUp() {
|
||||
bridge.publish(events.ConnStatusUp{})
|
||||
|
||||
func (bridge *Bridge) onStatusUp(ctx context.Context) {
|
||||
safe.RLock(func() {
|
||||
for _, user := range bridge.users {
|
||||
user.OnStatusUp()
|
||||
user.OnStatusUp(ctx)
|
||||
}
|
||||
}, bridge.usersLock)
|
||||
|
||||
bridge.goLoad()
|
||||
}
|
||||
|
||||
func (bridge *Bridge) onStatusDown() {
|
||||
bridge.publish(events.ConnStatusDown{})
|
||||
|
||||
func (bridge *Bridge) onStatusDown(ctx context.Context) {
|
||||
safe.RLock(func() {
|
||||
for _, user := range bridge.users {
|
||||
user.OnStatusDown()
|
||||
user.OnStatusDown(ctx)
|
||||
}
|
||||
}, bridge.usersLock)
|
||||
|
||||
bridge.tasks.Once(func(ctx context.Context) {
|
||||
backoff := time.Second
|
||||
for backoff := time.Second; ; backoff = min(backoff*2, 30*time.Second) {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
case <-time.After(backoff):
|
||||
if err := bridge.api.Ping(ctx); err != nil {
|
||||
logrus.WithError(err).Debug("Failed to ping API, will retry")
|
||||
} else {
|
||||
return
|
||||
|
||||
case <-time.After(backoff):
|
||||
if err := bridge.api.Ping(ctx); err != nil {
|
||||
logrus.WithError(err).Debug("Failed to ping API, will retry")
|
||||
} else {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if backoff < 30*time.Second {
|
||||
backoff *= 2
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func loadTLSConfig(vault *vault.Vault) (*tls.Config, error) {
|
||||
@ -502,3 +492,11 @@ func newListener(port int, useTLS bool, tlsConfig *tls.Config) (net.Listener, er
|
||||
|
||||
return netListener, nil
|
||||
}
|
||||
|
||||
func min(a, b time.Duration) time.Duration {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
@ -522,12 +522,12 @@ func (user *User) CheckAuth(email string, password []byte) (string, error) {
|
||||
}
|
||||
|
||||
// OnStatusUp is called when the connection goes up.
|
||||
func (user *User) OnStatusUp() {
|
||||
func (user *User) OnStatusUp(context.Context) {
|
||||
user.goSync()
|
||||
}
|
||||
|
||||
// OnStatusDown is called when the connection goes down.
|
||||
func (user *User) OnStatusDown() {
|
||||
func (user *User) OnStatusDown(context.Context) {
|
||||
user.abortable.Abort()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user