Skip to content

Commit 4d78e9e

Browse files
tomokinattwifkak
authored andcommitted
make stop channel work properly for both maintainCerts and maintainOCSP (#379)
1 parent 8673537 commit 4d78e9e

File tree

3 files changed

+25
-13
lines changed

3 files changed

+25
-13
lines changed

cmd/amppkg/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ func main() {
9898
die(errors.Wrap(err, "building cert cache"))
9999
}
100100

101-
if err = certCache.Init(nil); err != nil {
101+
if err = certCache.Init(); err != nil {
102102
if *flagDevelopment {
103103
fmt.Println("WARNING:", err)
104104
} else {

packager/certcache/certcache.go

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ type CertCache struct {
8888
renewedCerts []*x509.Certificate
8989
ocspUpdateAfterMu sync.RWMutex
9090
ocspUpdateAfter time.Time
91+
stop chan struct{}
9192
// TODO(twifkak): Implement a registry of Updateable instances which can be configured in the toml.
9293
ocspFile Updateable
9394
ocspFilePath string
@@ -141,6 +142,7 @@ func New(certs []*x509.Certificate, certFetcher *certfetcher.CertFetcher, domain
141142
// you'd have one request, in the backend, and updating them all.
142143
ocspFile: &Chained{first: &InMemory{}, second: &LocalFile{path: ocspCache}},
143144
ocspFilePath: ocspCache,
145+
stop: make(chan struct{}),
144146
generateOCSPResponse: generateOCSPResponse,
145147
client: http.Client{Timeout: 60 * time.Second},
146148
extractOCSPServer: func(cert *x509.Certificate) (string, error) {
@@ -165,7 +167,7 @@ func New(certs []*x509.Certificate, certFetcher *certfetcher.CertFetcher, domain
165167
}
166168
}
167169

168-
func (this *CertCache) Init(stop chan struct{}) error {
170+
func (this *CertCache) Init() error {
169171
this.updateCertIfNecessary()
170172

171173
// Prime the OCSP disk and memory cache, so we can start serving immediately.
@@ -181,18 +183,31 @@ func (this *CertCache) Init(stop chan struct{}) error {
181183
// like the OCSP responder giving you junk, but also sufficient time
182184
// to raise an alert if something has gone really wrong.
183185
// 7. The ability to serve old responses while fetching new responses.
184-
go this.maintainOCSP(stop)
186+
go this.maintainOCSP()
185187

186188
if this.certFetcher != nil {
187189
// Update Certs in the background.
188-
go this.maintainCerts(stop)
190+
go this.maintainCerts()
189191
}
190192

191193
this.isInitialized = true
192194

193195
return nil
194196
}
195197

198+
// Stop stops the goroutines spawned in Init, which are automatically updating the certificate and the OCSP response.
199+
// It returns true if the call actually stops them, false if they have already been stopped.
200+
func (this *CertCache) Stop() bool {
201+
select {
202+
// this.stop will never be used for sending a value. Thus this case matches only when it has already been closed.
203+
case <-this.stop:
204+
return false
205+
default:
206+
close(this.stop)
207+
return true
208+
}
209+
}
210+
196211
// Gets the latest cert.
197212
// Returns the current cert if the cache has not been initialized or if the certFetcher is not set (good for testing)
198213
// If cert is invalid, it will attempt to renew.
@@ -422,7 +437,7 @@ func waitForSpecifiedTime(waitTimeInMinutes int, numRetries int) int {
422437

423438
// Checks for OCSP updates every hour. Terminates only when stop receives
424439
// a message.
425-
func (this *CertCache) maintainOCSP(stop chan struct{}) {
440+
func (this *CertCache) maintainOCSP() {
426441
// Only make one request per ocspCheckInterval, to minimize the impact
427442
// on OCSP servers that are buckling under load, per sleevi requirement:
428443
// 5. As with any system doing background requests on a remote server,
@@ -440,7 +455,7 @@ func (this *CertCache) maintainOCSP(stop chan struct{}) {
440455
if err != nil {
441456
log.Println("Warning: OCSP update failed. Cached response may expire:", err)
442457
}
443-
case <-stop:
458+
case <-this.stop:
444459
ticker.Stop()
445460
return
446461
}
@@ -635,7 +650,7 @@ func (this *CertCache) fetchOCSP(orig []byte, certs []*x509.Certificate, ocspUpd
635650

636651
// Checks for cert updates every certCheckInterval hours. Terminates only when stop
637652
// receives a message.
638-
func (this *CertCache) maintainCerts(stop chan struct{}) {
653+
func (this *CertCache) maintainCerts() {
639654
// Only make one request per certCheckInterval, to minimize the impact
640655
// on servers that are buckling under load.
641656
ticker := time.NewTicker(certCheckInterval)
@@ -644,7 +659,7 @@ func (this *CertCache) maintainCerts(stop chan struct{}) {
644659
select {
645660
case <-ticker.C:
646661
this.updateCertIfNecessary()
647-
case <-stop:
662+
case <-this.stop:
648663
ticker.Stop()
649664
return
650665
}

packager/certcache/certcache_test.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ type CertCacheSuite struct {
6868
ocspServerWasCalled bool
6969
ocspHandler func(w http.ResponseWriter, req *http.Request)
7070
tempDir string
71-
stop chan struct{}
7271
handler *CertCache
7372
}
7473

@@ -93,7 +92,7 @@ func (this *CertCacheSuite) New() (*CertCache, error) {
9392
return defaultHttpExpiry(req, resp)
9493
}
9594
}
96-
err := certCache.Init(this.stop)
95+
err := certCache.Init()
9796
return certCache, err
9897
}
9998

@@ -121,8 +120,6 @@ func (this *CertCacheSuite) SetupTest() {
121120
this.tempDir, err = ioutil.TempDir(os.TempDir(), "certcache_test")
122121
this.Require().NoError(err, "setting up test harness")
123122

124-
this.stop = make(chan struct{})
125-
126123
this.handler, err = this.New()
127124
this.Require().NoError(err, "instantiating CertCache")
128125
}
@@ -132,7 +129,7 @@ func (this *CertCacheSuite) TearDownTest() {
132129
this.fakeOCSPExpiry = nil
133130

134131
// Reverse SetupTest.
135-
this.stop <- struct{}{}
132+
this.handler.Stop()
136133

137134
err := os.RemoveAll(this.tempDir)
138135
if err != nil {

0 commit comments

Comments
 (0)