You've already forked alertmanager
mirror of
https://github.com/prometheus/alertmanager.git
synced 2026-10-26 08:39:24 +03:00
httpserver: make /-/reload handler cancellation-safe
Fix three bugs in the reload handler identified in #5103: 1. Use a buffered error channel (size 1) so the reloader goroutine never blocks if the HTTP client disconnects before reading the result. 2. Remove the incorrect `defer close(errc)` — the handler is the receiver, not the sender; closing from the receiver side could panic the sender. 3. Wrap both the enqueue (send to reloadCh) and the reply (receive from errc) in select statements that also listen on req.Context().Done(), so a client disconnect unblocks the handler at either stage. Fixes #5103 Signed-off-by: June Kim <kimjune01@gmail.com> Signed-off-by: Solomon Jacobs <solomonjacobs@protonmail.com>
This commit is contained in:
@@ -29,12 +29,22 @@ func Register(r *route.Router, reloadCh chan<- chan error) {
|
||||
r.Get("/metrics", promhttp.Handler().ServeHTTP)
|
||||
|
||||
r.Post("/-/reload", func(w http.ResponseWriter, req *http.Request) {
|
||||
errc := make(chan error)
|
||||
defer close(errc)
|
||||
errc := make(chan error, 1)
|
||||
|
||||
reloadCh <- errc
|
||||
if err := <-errc; err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to reload config: %s", err), http.StatusInternalServerError)
|
||||
select {
|
||||
case reloadCh <- errc:
|
||||
case <-req.Context().Done():
|
||||
http.Error(w, req.Context().Err().Error(), http.StatusUnprocessableEntity)
|
||||
return
|
||||
}
|
||||
|
||||
select {
|
||||
case err := <-errc:
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("failed to reload config: %s", err), http.StatusInternalServerError)
|
||||
}
|
||||
case <-req.Context().Done():
|
||||
http.Error(w, req.Context().Err().Error(), http.StatusUnprocessableEntity)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user