Repository: etcd-io/etcd
File: server/embed/etcd.go (Go)

Code before:
func (e *Etcd) grpcGatewayDial(splitHTTP bool) (grpcDial func(ctx context.Context) (*grpc.ClientConn, error)) {
	if !e.cfg.EnableGRPCGateway {
		return nil
	}
	sctx := e.pickGRPCGatewayServeContext(splitHTTP)
	addr := sctx.addr
	if network := sctx.network; network == "unix" {
		// explicitly define unix network for gRPC socket support
		addr = fmt.Sprintf("%s:%s", network, addr)
	}
	opts := []grpc.DialOption{grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(math.MaxInt32))}
	if sctx.secure {
		tlscfg, tlsErr := e.cfg.ClientTLSInfo.ServerConfig()
		if tlsErr != nil {
			return func(ctx context.Context) (*grpc.ClientConn, error) {
				return nil, tlsErr
			}
		}
		dtls := tlscfg.Clone()
		// trust local server
		dtls.InsecureSkipVerify = true
		opts = append(opts, grpc.WithTransportCredentials(credentials.NewTransportCredential(dtls)))
	} else {
		opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials()))
	}

	return func(ctx context.Context) (*grpc.ClientConn, error) {
		conn, err := grpc.DialContext(ctx, addr, opts...)
		if err != nil {
			sctx.lg.Error("grpc gateway failed to dial", zap.String("addr", addr), zap.Error(err))
			return nil, err
		}
		return conn, err
	}
}

func (e *Etcd) pickGRPCGatewayServeContext(splitHTTP bool) *serveCtx {
	for _, sctx := range e.sctxs {
		if !splitHTTP || !sctx.httpOnly {
			return sctx
		}
	}
	panic("Expect at least one context able to serve grpc")
}

var ErrMissingClientTLSInfoForMetricsURL = errors.New("client TLS key/cert (--cert-file, --key-file) must be provided for metrics secure url")

func (e *Etcd) createMetricsListener(murl url.URL) (net.Listener, error) {
	tlsInfo := &e.cfg.ClientTLSInfo
	switch murl.Scheme {
	case "http":

Review comment (bug):
I would recommend wrapping the logic into a function to schedule a subroutine:

```
func (e *Etcd) runSubroutine(subroutine func() err) {
  e.wg.Add(1)
  go func() {
    defer e.wg.Done()
    err := subroutine()
     if err != nil {
        e.GetLogger().Error("setting up serving from embedded etcd failed.", zap.Error(err))
     }
      select {
      case <-e.stopc:
      return
      default:
      }
      select {
      case <-e.stopc:
      case e.errc <- err:
      }
      }()
}
```

Code after:
	var gopts []grpc.ServerOption
	if e.cfg.GRPCKeepAliveMinTime > time.Duration(0) {
		gopts = append(gopts, grpc.KeepaliveEnforcementPolicy(keepalive.EnforcementPolicy{
			MinTime:             e.cfg.GRPCKeepAliveMinTime,
			PermitWithoutStream: false,
		}))
	}
	if e.cfg.GRPCKeepAliveInterval > time.Duration(0) &&
		e.cfg.GRPCKeepAliveTimeout > time.Duration(0) {
		gopts = append(gopts, grpc.KeepaliveParams(keepalive.ServerParameters{
			Time:    e.cfg.GRPCKeepAliveInterval,
			Timeout: e.cfg.GRPCKeepAliveTimeout,
		}))
	}
	gopts = append(gopts, e.cfg.GRPCAdditionalServerOptions...)

	splitHTTP := false
	for _, sctx := range e.sctxs {
		if sctx.httpOnly {
			splitHTTP = true
		}
	}

	// start client servers in each goroutine
	for _, sctx := range e.sctxs {
		e.wg.Add(1)
		go func(s *serveCtx) {
			defer e.wg.Done()
			e.errHandler(s.serve(e.Server, &e.cfg.ClientTLSInfo, mux, e.errHandler, e.grpcGatewayDial(splitHTTP), splitHTTP, gopts...))
		}(sctx)
	}
}

func (e *Etcd) grpcGatewayDial(splitHTTP bool) (grpcDial func(ctx context.Context) (*grpc.ClientConn, error)) {
	if !e.cfg.EnableGRPCGateway {
		return nil
	}
	sctx := e.pickGRPCGatewayServeContext(splitHTTP)
	addr := sctx.addr
	if network := sctx.network; network == "unix" {
		// explicitly define unix network for gRPC socket support
		addr = fmt.Sprintf("%s:%s", network, addr)
	}
	opts := []grpc.DialOption{grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(math.MaxInt32))}
	if sctx.secure {
		tlscfg, tlsErr := e.cfg.ClientTLSInfo.ServerConfig()
		if tlsErr != nil {
			return func(ctx context.Context) (*grpc.ClientConn, error) {
				return nil, tlsErr
			}
		}