fix(offlinegate): avoid leaking an RLock when the handler panics BE-11495 (#234)

release/2.25
andres-portainer 2024-12-11 16:38:03 -03:00 committed by GitHub
parent e1388eff84
commit 94fda6a720
2 changed files with 31 additions and 1 deletions

View File

@ -45,7 +45,9 @@ func (o *OfflineGate) WaitingMiddleware(timeout time.Duration, next http.Handler
httperror.WriteError(w, http.StatusRequestTimeout, "Request timed out while waiting for the backup process to finish", http.ErrHandlerTimeout) httperror.WriteError(w, http.StatusRequestTimeout, "Request timed out while waiting for the backup process to finish", http.ErrHandlerTimeout)
return return
} }
defer o.lock.RUnlock()
next.ServeHTTP(w, r) next.ServeHTTP(w, r)
o.lock.RUnlock()
}) })
} }

View File

@ -9,6 +9,7 @@ import (
"time" "time"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
func Test_canLockAndUnlock(t *testing.T) { func Test_canLockAndUnlock(t *testing.T) {
@ -146,3 +147,30 @@ func Test_waitingMiddleware_mayTimeout_whenLockedForTooLong(t *testing.T) {
assert.Equal(t, http.StatusRequestTimeout, response.Result().StatusCode, "Request support to timeout waiting for the gate") assert.Equal(t, http.StatusRequestTimeout, response.Result().StatusCode, "Request support to timeout waiting for the gate")
} }
func Test_waitingMiddleware_handlerPanics(t *testing.T) {
o := NewOfflineGate()
request := httptest.NewRequest(http.MethodPost, "/", nil)
response := httptest.NewRecorder()
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
defer func() {
recover()
wg.Done()
}()
o.WaitingMiddleware(time.Second, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
panic("panic")
})).ServeHTTP(response, request)
}()
wg.Wait()
require.True(t, o.lock.TryLock())
o.lock.Unlock()
}