code: func (cg configGroup) renewDynamicCertificate(name string, cfg *Config) (Certificate, error) {
  	obtainCertWaitChansMu.Lock()
  	wait, ok := obtainCertWaitChans[name]
  	if ok {
  		// lucky us -- another goroutine is already renewing the certificate.
  		// wait for it to finish, then we'll use the new one.
  		obtainCertWaitChansMu.Unlock()
  		<-wait
  		return cg.getCertDuringHandshake(name, true, false)
  	}
  
  	// looks like it's up to us to do all the work and renew the cert
  	wait = make(chan struct{})
  	obtainCertWaitChans[name] = wait
  	obtainCertWaitChansMu.Unlock()
  
  	// do the renew
  	log.Printf("[INFO] Renewing certificate for %s", name)
  	err := cfg.RenewCert(name, false)
  
  	// immediately unblock anyone waiting for it; doing this in
  	// a defer would risk deadlock because of the recursive call
  	// to getCertDuringHandshake below when we return!
  	obtainCertWaitChansMu.Lock()
  	close(wait)
  	delete(obtainCertWaitChans, name)
  	obtainCertWaitChansMu.Unlock()
  
  	if err != nil {
  		return Certificate{}, err
  	}
  
  	return cg.getCertDuringHandshake(name, true, false)
  }
docs: // renewDynamicCertificate renews the certificate for name using cfg. It returns the
  // certificate to use and an error, if any. currentCert may be returned even if an
  // error occurs, since we perform renewals before they expire and it may still be
  // usable. name should already be lower-cased before calling this function.
  //
  // This function is safe for use by multiple concurrent goroutines.