Make caser a local varialbe, not a global one.
authorMarcelo E. Magallon <marcelo.magallon@grafana.com>
Mon, 13 Jun 2022 23:21:41 +0000 (17:21 -0600)
committerJulien Pivotto <roidelapluie@gmail.com>
Fri, 17 Jun 2022 12:21:50 +0000 (14:21 +0200)
The cases.Caser returned by calling cases.Title *cannot* be shared among
goroutines. This might happen when Prometheus tries to scrape multiple
targets at the same time. From the docs:

A Caser may be stateful and should therefore not be shared between
goroutines.

Fixes: #922

Signed-off-by: Marcelo E. Magallon <marcelo.magallon@grafana.com>
prober/http.go
prober/http_test.go

index 54f40998f968210d34219b1a71f21e8e4dde55fc..99d38a2bf592281448d80ff8bcef1f831ab35eb7 100644 (file)
@@ -46,8 +46,6 @@ import (
        "github.com/prometheus/blackbox_exporter/config"
 )
 
-var caser = cases.Title(language.Und)
-
 func matchRegularExpressions(reader io.Reader, httpConfig config.HTTPProbe, logger log.Logger) bool {
        body, err := ioutil.ReadAll(reader)
        if err != nil {
@@ -342,6 +340,16 @@ func ProbeHTTP(ctx context.Context, target string, module config.Module, registr
                return false
        }
 
+       // Do not move the following variable to global scope. The cases.Caser returned by
+       // calling cases.Title *cannot* be shared among goroutines. This might happen when
+       // Prometheus tries to scrape multiple targets at the same time. From the docs:
+       //
+       // A Caser may be stateful and should therefore not be shared between goroutines.
+       //
+       // Issue: https://github.com/prometheus/blackbox_exporter/issues/922
+
+       caser := cases.Title(language.Und)
+
        httpClientConfig := module.HTTP.HTTPClientConfig
        if len(httpClientConfig.TLSConfig.ServerName) == 0 {
                // If there is no `server_name` in tls_config, use
index dc5b65bbd09879f22698efa256f7a2352a4c56c2..cd277618aa33b4158661ebae5365d4f97f4fa6d5 100644 (file)
@@ -35,6 +35,8 @@ import (
        "github.com/go-kit/log"
        "github.com/prometheus/client_golang/prometheus"
        pconfig "github.com/prometheus/common/config"
+       "golang.org/x/text/cases"
+       "golang.org/x/text/language"
 
        "github.com/prometheus/blackbox_exporter/config"
 )
@@ -1068,6 +1070,7 @@ func TestHTTPHeaders(t *testing.T) {
                "Accept-Language": "en-US",
        }
        ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+               caser := cases.Title(language.Und)
                for key, value := range headers {
                        if caser.String(key) == "Host" {
                                if r.Host != value {