Skip to content

Commit 037d470

Browse files
committed
Bugfixes
1 parent 2a85ef6 commit 037d470

File tree

3 files changed

+42
-26
lines changed

3 files changed

+42
-26
lines changed

certs/certificate2.go

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -67,20 +67,22 @@ func NewCertificate2(certFile, keyFile string) (*Certificate2, error) {
6767
var wg sync.WaitGroup
6868

6969
var c Certificate2
70+
var once sync.Once
7071
c.close = func() {
71-
c.close = nil // don't run multiple times
72-
notify.Stop(ch)
73-
cancel()
74-
wg.Wait() // don't close channel before goroutine is done
75-
close(ch)
76-
77-
c.lock.Lock()
78-
subs := c.subscriptions
79-
c.subscriptions = nil
80-
c.lock.Unlock()
81-
for _, sub := range subs {
82-
close(sub)
83-
}
72+
once.Do(func() {
73+
notify.Stop(ch)
74+
cancel()
75+
wg.Wait() // don't close channel before goroutine is done
76+
close(ch)
77+
78+
c.lock.Lock()
79+
subs := c.subscriptions
80+
c.subscriptions = nil
81+
c.lock.Unlock()
82+
for _, sub := range subs {
83+
close(sub)
84+
}
85+
})
8486
}
8587
c.Store(&cert)
8688

@@ -98,10 +100,12 @@ func NewCertificate2(certFile, keyFile string) (*Certificate2, error) {
98100
certPEMBlock, err := os.ReadFile(certFile)
99101
if err != nil {
100102
log.Printf("reloading certificate failed: %s", err)
103+
continue
101104
}
102105
keyPEMBlock, err := os.ReadFile(keyFile)
103106
if err != nil {
104107
log.Printf("reloading key failed: %s", err)
108+
continue
105109
}
106110
newCertHash := sha256.Sum256(certPEMBlock)
107111
newKeyHash := sha256.Sum256(keyPEMBlock)
@@ -126,7 +130,11 @@ func NewCertificate2(certFile, keyFile string) (*Certificate2, error) {
126130
subs := append([]chan *Certificate2{}, c.subscriptions...)
127131
c.lock.Unlock()
128132
for _, sub := range subs {
129-
sub <- &c
133+
select {
134+
case sub <- &c:
135+
default:
136+
log.Printf("certificate update notification dropped: subscriber channel full")
137+
}
130138
}
131139
}()
132140
}
@@ -167,9 +175,7 @@ func (c *Certificate2) Subscribe(callback func(*Certificate2)) func() {
167175

168176
// Close stops watching the certificate files and releases all resources.
169177
func (c *Certificate2) Close() {
170-
if cl := c.close; cl != nil {
171-
cl()
172-
}
178+
c.close()
173179
}
174180

175181
func watchFile(ctx context.Context, path string, ch chan notify.EventInfo, wg *sync.WaitGroup) error {

certs/global_certs.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import (
2424
)
2525

2626
var (
27-
globalCerts map[string]*Certificate2
27+
globalCerts map[string]*Certificate2 // once a certificate is loaded, we keep it here forever
2828
globalCertsLock sync.Mutex
2929
)
3030

@@ -55,7 +55,7 @@ func globalCertificate(certFile, keyFile string) (*Certificate2, error) {
5555
}
5656

5757
// GetClientCertificate returns a function that returns the given
58-
// certificate/key pair for use in tls.Config.ClientCertificate.
58+
// certificate/key pair for use in tls.Config.GetClientCertificate.
5959
func GetClientCertificate(certFile, keyFile string) (func(*tls.CertificateRequestInfo) (*tls.Certificate, error), error) {
6060
cert, err := globalCertificate(certFile, keyFile)
6161
if err != nil {

certs/manager2.go

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,32 +48,38 @@ type Manager2 struct {
4848
// The manager is using internal synchronization and is safe for concurrent
4949
// use. Make sure to call Close when the manager is no longer needed.
5050
func NewManager2(loadCerts func() ([]*Certificate2, error)) (*Manager2, error) {
51+
certUpdateCh := make(chan *Certificate2, 1)
52+
5153
// Load initial certificates
5254
certs, err := loadCerts()
5355
if err != nil {
5456
return nil, err
5557
}
5658

59+
// Subscribe to initial certificates
60+
for _, cert := range certs {
61+
// no need to store the close function, because
62+
// certificates are closed when they are replaced
63+
// and that will automatically close all subscriptions.
64+
cert.Subscribe(func(updatedCert *Certificate2) {
65+
certUpdateCh <- updatedCert
66+
})
67+
}
68+
5769
closeCh := make(chan struct{})
5870

5971
mgr := Manager2{
6072
close: closeCh,
6173
}
6274
mgr.certs.Store(&certs)
6375

64-
certUpdateCh := make(chan *Certificate2, 1)
65-
6676
replaceCerts := func(newCerts []*Certificate2) {
6777
oldCerts := mgr.certs.Swap(&newCerts)
6878
for i := range *oldCerts {
6979
(*oldCerts)[i].Close()
7080
}
7181

72-
// Subscribe to new certificates
7382
for _, cert := range newCerts {
74-
// no need to store the close function, because
75-
// certificates are closed when they are replaced
76-
// and that will automatically close all subscriptions.
7783
cert.Subscribe(func(updatedCert *Certificate2) {
7884
certUpdateCh <- updatedCert
7985
})
@@ -106,7 +112,11 @@ func NewManager2(loadCerts func() ([]*Certificate2, error)) (*Manager2, error) {
106112
subs := append([]chan *Certificate2{}, mgr.subscriptions...)
107113
mgr.subscriptionLock.Unlock()
108114
for _, sub := range subs {
109-
sub <- cert
115+
select {
116+
case sub <- cert:
117+
default:
118+
log.Printf("certificate update notification dropped: subscriber channel full")
119+
}
110120
}
111121
case <-signalCh:
112122
certs, err := loadCerts()

0 commit comments

Comments
 (0)