fix data race in CertificateReloader with RWMutex

This commit is contained in:
m5r
2026-01-18 11:20:15 +01:00
parent abb97cce56
commit f86e78f01d

View File

@@ -9,6 +9,7 @@ import (
"os" "os"
"strconv" "strconv"
"strings" "strings"
"sync"
"time" "time"
"github.com/urfave/negroni" "github.com/urfave/negroni"
@@ -145,6 +146,7 @@ func redirectHttpToHttps() {
type CertificateReloader struct { type CertificateReloader struct {
CertificateFilePath string CertificateFilePath string
KeyFilePath string KeyFilePath string
mu sync.RWMutex
certificate *tls.Certificate certificate *tls.Certificate
lastUpdatedAt time.Time lastUpdatedAt time.Time
} }
@@ -155,16 +157,27 @@ func (cr *CertificateReloader) GetCertificate(*tls.ClientHelloInfo) (*tls.Certif
return nil, fmt.Errorf("failed checking key file modification time: %w", err) return nil, fmt.Errorf("failed checking key file modification time: %w", err)
} }
if cr.certificate == nil || stat.ModTime().After(cr.lastUpdatedAt) { cr.mu.RLock()
pair, err := tls.LoadX509KeyPair(cr.CertificateFilePath, cr.KeyFilePath) if cr.certificate != nil && !stat.ModTime().After(cr.lastUpdatedAt) {
if err != nil { defer cr.mu.RUnlock()
return nil, fmt.Errorf("failed loading tls key pair: %w", err) return cr.certificate, nil
} }
cr.mu.RUnlock()
cr.certificate = &pair cr.mu.Lock()
cr.lastUpdatedAt = stat.ModTime() defer cr.mu.Unlock()
if cr.certificate != nil && !stat.ModTime().After(cr.lastUpdatedAt) {
return cr.certificate, nil
} }
pair, err := tls.LoadX509KeyPair(cr.CertificateFilePath, cr.KeyFilePath)
if err != nil {
return nil, fmt.Errorf("failed loading tls key pair: %w", err)
}
cr.certificate = &pair
cr.lastUpdatedAt = stat.ModTime()
return cr.certificate, nil return cr.certificate, nil
} }