mirror of https://github.com/prometheus/prometheus
Fix panic with double close() of channel on /-/quit/ (#8166)
Signed-off-by: Julien Pivotto <roidelapluie@inuits.eu>pull/8170/head
parent
4513537034
commit
cda52234eb
|
@ -918,8 +918,13 @@ func (h *Handler) version(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) quit(w http.ResponseWriter, r *http.Request) {
|
func (h *Handler) quit(w http.ResponseWriter, r *http.Request) {
|
||||||
fmt.Fprintf(w, "Requesting termination... Goodbye!")
|
select {
|
||||||
close(h.quitCh)
|
case <-h.quitCh:
|
||||||
|
fmt.Fprintf(w, "Termination already in progress.")
|
||||||
|
default:
|
||||||
|
fmt.Fprintf(w, "Requesting termination... Goodbye!")
|
||||||
|
close(h.quitCh)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) reload(w http.ResponseWriter, r *http.Request) {
|
func (h *Handler) reload(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
|
@ -27,6 +27,7 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -451,6 +452,60 @@ func TestShutdownWithStaleConnection(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestHandleMultipleQuitRequests(t *testing.T) {
|
||||||
|
opts := &Options{
|
||||||
|
ListenAddress: ":9090",
|
||||||
|
MaxConnections: 512,
|
||||||
|
EnableLifecycle: true,
|
||||||
|
RoutePrefix: "/",
|
||||||
|
ExternalURL: &url.URL{
|
||||||
|
Scheme: "http",
|
||||||
|
Host: "localhost:9090",
|
||||||
|
Path: "/",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
webHandler := New(nil, opts)
|
||||||
|
webHandler.config = &config.Config{}
|
||||||
|
webHandler.notifier = ¬ifier.Manager{}
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
closed := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
err := webHandler.Run(ctx)
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("Can't start web handler:%s", err))
|
||||||
|
}
|
||||||
|
close(closed)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Give some time for the web goroutine to run since we need the server
|
||||||
|
// to be up before starting tests.
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
|
||||||
|
start := make(chan struct{})
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
for i := 0; i < 3; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
<-start
|
||||||
|
resp, err := http.Post("http://localhost:9090/-/quit", "", strings.NewReader(""))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
close(start)
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
// Stop the web handler.
|
||||||
|
cancel()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-closed:
|
||||||
|
case <-time.After(5 * time.Second):
|
||||||
|
t.Fatalf("Server still running after 5 seconds.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func cleanupTestResponse(t *testing.T, resp *http.Response) {
|
func cleanupTestResponse(t *testing.T, resp *http.Response) {
|
||||||
_, err := io.Copy(ioutil.Discard, resp.Body)
|
_, err := io.Copy(ioutil.Discard, resp.Body)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
Loading…
Reference in New Issue