Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitaly.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Steinhardt <psteinhardt@gitlab.com>2022-09-23 10:48:35 +0300
committerPatrick Steinhardt <psteinhardt@gitlab.com>2022-09-23 10:48:35 +0300
commitc13d9d902ef8175a0b1165ef0bc8643fb37b7897 (patch)
treea113990da37b7d7cdce457de8c1298e636bff350
parent9498ab9459048cc595d8e2e411b027d080c0ab0f (diff)
parent5cccaa21826849eb3b57a32325e9cc3ec19c5e40 (diff)
Merge branch 'pks-golangci-lint-errcheck-improvements' into 'master'
golangci-lint: Stop excluding many `Close` and `Serve` functions from errcheck linter See merge request https://gitlab.com/gitlab-org/gitaly/-/merge_requests/4810 Merged-by: Patrick Steinhardt <psteinhardt@gitlab.com> Approved-by: Quang-Minh Nguyen <qmnguyen@gitlab.com> Approved-by: Pavlo Strokov <pstrokov@gitlab.com>
-rw-r--r--.golangci.yml23
-rw-r--r--client/dial_test.go14
-rw-r--r--client/upload_pack.go14
-rw-r--r--cmd/gitaly-hooks/hooks.go15
-rw-r--r--cmd/gitaly-ssh/auth_test.go2
-rw-r--r--internal/backchannel/backchannel_test.go4
-rw-r--r--internal/backchannel/server.go16
-rw-r--r--internal/cache/diskcache.go10
-rw-r--r--internal/cache/keyer.go10
-rw-r--r--internal/git/gittest/http_server.go3
-rw-r--r--internal/gitaly/archive/tar_builder.go2
-rw-r--r--internal/gitaly/client/dial_test.go2
-rw-r--r--internal/gitaly/hook/sidechannel.go15
-rw-r--r--internal/gitaly/hook/sidechannel_test.go3
-rw-r--r--internal/gitaly/linguist/language_stats.go5
-rw-r--r--internal/gitaly/server/auth_test.go4
-rw-r--r--internal/gitaly/server/server_factory_test.go6
-rw-r--r--internal/gitaly/service/hook/pack_objects_test.go10
-rw-r--r--internal/gitaly/service/repository/apply_gitattributes.go10
-rw-r--r--internal/gitaly/service/smarthttp/upload_pack_test.go8
-rw-r--r--internal/gitaly/storage/metadata.go11
-rw-r--r--internal/gitlab/test_server.go2
-rw-r--r--internal/helper/chunk/chunker_test.go2
-rw-r--r--internal/middleware/limithandler/middleware_test.go2
-rw-r--r--internal/praefect/auth_test.go2
-rw-r--r--internal/praefect/delete_object_pool_test.go6
-rw-r--r--internal/praefect/grpc-proxy/proxy/handler_ext_test.go6
-rw-r--r--internal/praefect/grpc-proxy/proxy/testhelper_test.go4
-rw-r--r--internal/praefect/middleware/errorhandler_test.go4
-rw-r--r--internal/praefect/node_test.go2
-rw-r--r--internal/praefect/nodes/sql_elector_test.go2
-rw-r--r--internal/praefect/remove_repository_test.go2
-rw-r--r--internal/praefect/replicator_pg_test.go4
-rw-r--r--internal/praefect/repository_exists_test.go2
-rw-r--r--internal/praefect/server_factory_test.go17
-rw-r--r--internal/praefect/server_test.go6
-rw-r--r--internal/sidechannel/proxy.go7
-rw-r--r--internal/sidechannel/proxy_test.go4
-rw-r--r--internal/sidechannel/registry_test.go5
-rw-r--r--internal/sidechannel/sidechannel_test.go10
-rw-r--r--internal/testhelper/testhelper.go21
-rw-r--r--packed_binaries.go14
42 files changed, 219 insertions, 92 deletions
diff --git a/.golangci.yml b/.golangci.yml
index 2c667e980..f97d22a09 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -46,6 +46,26 @@ linters-settings:
include-go-root: true
packages-with-error-message:
- io/ioutil: "ioutil is deprecated starting with Go 1.16"
+ errcheck:
+ # The following are functions for which we are currently not consistently
+ # checking returned errors. This is not intended as a list of known-okay
+ # cases to skip the checks, but rather as a list of things we should
+ # eventually fix.
+ exclude-functions:
+ - (*database/sql.DB).Close
+ - (*database/sql.Rows).Close
+ - (*gitlab.com/gitlab-org/gitaly/v15/client.Pool).Close
+ - (*gitlab.com/gitlab-org/gitaly/v15/internal/sidechannel.ServerConn).Close
+ - (*gitlab.com/gitlab-org/gitaly/v15/internal/streamcache.pipe).Close
+ - (*gitlab.com/gitlab-org/gitaly/v15/internal/streamcache.pipeReader).Close
+ - (*google.golang.org/grpc.ClientConn).Close
+ - (*google.golang.org/grpc.ServerConn).Close
+ - (*io.PipeReader).Close
+ - (*io.PipeWriter).Close
+ - (*os.File).Close
+ - (io.Closer).Close
+ - (net.Conn).Close
+ - (net.Listener).Close
forbidigo:
forbid:
# Tests and code which use timing-based setups have repeatedly resulted
@@ -95,9 +115,6 @@ issues:
- forbidigo
# This fine thing excludes all paths which don't end with "_test.go".
path: "^([^_]|_([^t]|t([^e]|e([^s]|s([^t]|t([^\\.]|\\.([^g]|g[^o])))))))*$"
- - linters:
- - errcheck
- text: "Error return value of `[^`]+.(Close|Serve)` is not checked"
# Maximum issues count per one linter. Set to 0 to disable. Default is 50.
max-issues-per-linter: 0
# Maximum count of issues with the same text. Set to 0 to disable. Default is 3.
diff --git a/client/dial_test.go b/client/dial_test.go
index 758ff1013..e0870ee32 100644
--- a/client/dial_test.go
+++ b/client/dial_test.go
@@ -247,7 +247,7 @@ func TestDialSidechannel(t *testing.T) {
return nil
})
- defer scw.Close()
+ defer testhelper.MustClose(t, scw)
req := &healthpb.HealthCheckRequest{Service: "test sidechannel"}
_, err = healthpb.NewHealthClient(conn).Check(ctx, req)
@@ -296,7 +296,7 @@ func TestDial_Correlation(t *testing.T) {
}
grpc_testing.RegisterTestServiceServer(grpcServer, svc)
- go func() { assert.NoError(t, grpcServer.Serve(listener)) }()
+ go testhelper.MustServe(t, grpcServer, listener)
defer grpcServer.Stop()
ctx := testhelper.Context(t)
@@ -332,7 +332,7 @@ func TestDial_Correlation(t *testing.T) {
}
grpc_testing.RegisterTestServiceServer(grpcServer, svc)
- go func() { assert.NoError(t, grpcServer.Serve(listener)) }()
+ go testhelper.MustServe(t, grpcServer, listener)
defer grpcServer.Stop()
ctx := testhelper.Context(t)
@@ -395,7 +395,7 @@ func TestDial_Tracing(t *testing.T) {
}
grpc_testing.RegisterTestServiceServer(grpcServer, svc)
- go func() { require.NoError(t, grpcServer.Serve(listener)) }()
+ go testhelper.MustServe(t, grpcServer, listener)
defer grpcServer.Stop()
ctx := testhelper.Context(t)
@@ -543,7 +543,7 @@ func startTCPListener(tb testing.TB, factory func(credentials.TransportCredentia
address := fmt.Sprintf("%d", tcpPort)
grpcServer := factory(insecure.NewCredentials())
- go grpcServer.Serve(listener)
+ go testhelper.MustServe(tb, grpcServer, listener)
return func() {
grpcServer.Stop()
@@ -558,7 +558,7 @@ func startUnixListener(tb testing.TB, factory func(credentials.TransportCredenti
require.NoError(tb, err)
grpcServer := factory(insecure.NewCredentials())
- go grpcServer.Serve(listener)
+ go testhelper.MustServe(tb, grpcServer, listener)
return func() {
grpcServer.Stop()
@@ -583,7 +583,7 @@ func startTLSListener(tb testing.TB, factory func(credentials.TransportCredentia
MinVersion: tls.VersionTLS12,
}),
)
- go grpcServer.Serve(listener)
+ go testhelper.MustServe(tb, grpcServer, listener)
return func() {
grpcServer.Stop()
diff --git a/client/upload_pack.go b/client/upload_pack.go
index 863465068..aeda65f6b 100644
--- a/client/upload_pack.go
+++ b/client/upload_pack.go
@@ -43,14 +43,24 @@ func UploadPack(ctx context.Context, conn *grpc.ClientConn, stdin io.Reader, std
// UploadPackWithSidechannel proxies an SSH git-upload-pack (git fetch)
// session to Gitaly using a sidechannel for the raw data transfer.
-func UploadPackWithSidechannel(ctx context.Context, conn *grpc.ClientConn, reg *SidechannelRegistry, stdin io.Reader, stdout, stderr io.Writer, req *gitalypb.SSHUploadPackWithSidechannelRequest) (int32, error) {
+func UploadPackWithSidechannel(
+ ctx context.Context,
+ conn *grpc.ClientConn,
+ reg *SidechannelRegistry,
+ stdin io.Reader,
+ stdout, stderr io.Writer,
+ req *gitalypb.SSHUploadPackWithSidechannelRequest,
+) (int32, error) {
ctx, cancel := context.WithCancel(ctx)
defer cancel()
ctx, wt := reg.Register(ctx, func(c SidechannelConn) error {
return stream.ProxyPktLine(c, stdin, stdout, stderr)
})
- defer wt.Close()
+ defer func() {
+ // We aleady check the error further down.
+ _ = wt.Close()
+ }()
sshClient := gitalypb.NewSSHServiceClient(conn)
if _, err := sshClient.SSHUploadPackWithSidechannel(ctx, req); err != nil {
diff --git a/cmd/gitaly-hooks/hooks.go b/cmd/gitaly-hooks/hooks.go
index 39d0e4ba4..11601d29a 100644
--- a/cmd/gitaly-hooks/hooks.go
+++ b/cmd/gitaly-hooks/hooks.go
@@ -334,7 +334,10 @@ func handlePackObjectsWithSidechannel(ctx context.Context, payload git.HooksPayl
if err != nil {
return fmt.Errorf("SetupSidechannel: %w", err)
}
- defer wt.Close()
+ defer func() {
+ // We aleady check the error further down.
+ _ = wt.Close()
+ }()
var glID, glUsername, gitProtocol string
@@ -376,5 +379,13 @@ func handlePackObjectsWithSidechannel(ctx context.Context, payload git.HooksPayl
return fmt.Errorf("call PackObjectsHookWithSidechannel: %w", err)
}
- return wt.Wait()
+ if err := wt.Wait(); err != nil {
+ return err
+ }
+
+ if err := wt.Close(); err != nil {
+ return fmt.Errorf("closing sidechannel: %w", err)
+ }
+
+ return nil
}
diff --git a/cmd/gitaly-ssh/auth_test.go b/cmd/gitaly-ssh/auth_test.go
index 8a5921432..db33fbab3 100644
--- a/cmd/gitaly-ssh/auth_test.go
+++ b/cmd/gitaly-ssh/auth_test.go
@@ -167,7 +167,7 @@ func runServer(t *testing.T, secure bool, cfg config.Cfg, connectionType string,
listener, err := net.Listen(connectionType, addr)
require.NoError(t, err)
- go srv.Serve(listener)
+ go testhelper.MustServe(t, srv, listener)
port := 0
if connectionType != "unix" {
diff --git a/internal/backchannel/backchannel_test.go b/internal/backchannel/backchannel_test.go
index e8885629a..534b63962 100644
--- a/internal/backchannel/backchannel_test.go
+++ b/internal/backchannel/backchannel_test.go
@@ -78,7 +78,7 @@ func TestBackchannel_concurrentRequestsFromMultipleClients(t *testing.T) {
})
defer srv.Stop()
- go srv.Serve(ln)
+ go testhelper.MustServe(t, srv, ln)
ctx := testhelper.Context(t)
start := make(chan struct{})
@@ -271,7 +271,7 @@ func Benchmark(b *testing.B) {
require.NoError(b, err)
defer srv.Stop()
- go srv.Serve(ln)
+ go testhelper.MustServe(b, srv, ln)
ctx := testhelper.Context(b)
opts := []grpc.DialOption{grpc.WithBlock(), grpc.WithTransportCredentials(insecure.NewCredentials())}
diff --git a/internal/backchannel/server.go b/internal/backchannel/server.go
index 9e0f0537a..9b7e58bda 100644
--- a/internal/backchannel/server.go
+++ b/internal/backchannel/server.go
@@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
+ "io"
"net"
"github.com/hashicorp/yamux"
@@ -136,10 +137,17 @@ func (s *ServerHandshaker) Handshake(conn net.Conn, authInfo credentials.AuthInf
Conn: clientToServerStream,
close: func() error {
s.registry.RemoveBackchannel(id)
- backchannelConn.Close()
- muxSession.Close()
- logger.Close()
- return nil
+
+ var firstErr error
+ for _, closer := range []io.Closer{
+ backchannelConn, muxSession, logger,
+ } {
+ if err := closer.Close(); err != nil && firstErr == nil {
+ firstErr = err
+ }
+ }
+
+ return firstErr
},
},
withSessionInfo(authInfo, id, muxSession),
diff --git a/internal/cache/diskcache.go b/internal/cache/diskcache.go
index 192afde07..60408f4af 100644
--- a/internal/cache/diskcache.go
+++ b/internal/cache/diskcache.go
@@ -272,7 +272,7 @@ func (irc instrumentedReadCloser) Read(p []byte) (n int, err error) {
// PutStream will store a stream in a repo-namespace keyed by the digest of the
// request protobuf message.
-func (c *DiskCache) PutStream(ctx context.Context, repo *gitalypb.Repository, req proto.Message, src io.Reader) error {
+func (c *DiskCache) PutStream(ctx context.Context, repo *gitalypb.Repository, req proto.Message, src io.Reader) (returnedErr error) {
reqPath, err := c.KeyPath(ctx, repo, req)
if err != nil {
return err
@@ -298,7 +298,13 @@ func (c *DiskCache) PutStream(ctx context.Context, repo *gitalypb.Repository, re
if err != nil {
return err
}
- defer sf.Close()
+ defer func() {
+ if err := sf.Close(); err != nil && returnedErr == nil {
+ if !errors.Is(err, safe.ErrAlreadyDone) {
+ returnedErr = err
+ }
+ }
+ }()
n, err = io.Copy(sf, src)
if err != nil {
diff --git a/internal/cache/keyer.go b/internal/cache/keyer.go
index b89b240db..519edbd38 100644
--- a/internal/cache/keyer.go
+++ b/internal/cache/keyer.go
@@ -56,7 +56,7 @@ func newLeaseKeyer(locator storage.Locator, countErr func(error) error) leaseKey
}
}
-func (keyer leaseKeyer) updateLatest(ctx context.Context, repo *gitalypb.Repository) (string, error) {
+func (keyer leaseKeyer) updateLatest(ctx context.Context, repo *gitalypb.Repository) (_ string, returnedErr error) {
repoStatePath, err := keyer.getRepoStatePath(repo)
if err != nil {
return "", err
@@ -71,7 +71,13 @@ func (keyer leaseKeyer) updateLatest(ctx context.Context, repo *gitalypb.Reposit
if err != nil {
return "", err
}
- defer latest.Close()
+ defer func() {
+ if err := latest.Close(); err != nil && returnedErr == nil {
+ if !errors.Is(err, safe.ErrAlreadyDone) {
+ returnedErr = err
+ }
+ }
+ }()
nextGenID := uuid.New().String()
if nextGenID == "" {
diff --git a/internal/git/gittest/http_server.go b/internal/git/gittest/http_server.go
index d55f2987a..a0ac490f3 100644
--- a/internal/git/gittest/http_server.go
+++ b/internal/git/gittest/http_server.go
@@ -11,6 +11,7 @@ import (
"github.com/stretchr/testify/require"
"gitlab.com/gitlab-org/gitaly/v15/internal/git"
+ "gitlab.com/gitlab-org/gitaly/v15/internal/testhelper"
)
// HTTPServer starts an HTTP server with git-http-backend(1) as CGI handler. The repository is
@@ -43,7 +44,7 @@ func HTTPServer(ctx context.Context, tb testing.TB, gitCmdFactory git.CommandFac
})
}
- go s.Serve(listener)
+ go testhelper.MustServe(tb, &s, listener)
return listener.Addr().(*net.TCPAddr).Port, s.Close
}
diff --git a/internal/gitaly/archive/tar_builder.go b/internal/gitaly/archive/tar_builder.go
index 2ae1a0b32..3e93e273e 100644
--- a/internal/gitaly/archive/tar_builder.go
+++ b/internal/gitaly/archive/tar_builder.go
@@ -196,7 +196,7 @@ func (t *TarBuilder) Close() error {
if t.err != nil {
// Ignore any close error in favour of reporting the previous one, but
// ensure the tar writer is closed to avoid resource leaks
- t.tarWriter.Close()
+ _ = t.tarWriter.Close()
return t.err
}
diff --git a/internal/gitaly/client/dial_test.go b/internal/gitaly/client/dial_test.go
index 9c9f72f17..2ff52e9b8 100644
--- a/internal/gitaly/client/dial_test.go
+++ b/internal/gitaly/client/dial_test.go
@@ -44,7 +44,7 @@ func TestDial(t *testing.T) {
ln, err := net.Listen("tcp", "localhost:0")
require.NoError(t, err)
- go srv.Serve(ln)
+ go testhelper.MustServe(t, srv, ln)
ctx := testhelper.Context(t)
t.Run("non-muxed conn", func(t *testing.T) {
diff --git a/internal/gitaly/hook/sidechannel.go b/internal/gitaly/hook/sidechannel.go
index 62c32a059..14fa5304e 100644
--- a/internal/gitaly/hook/sidechannel.go
+++ b/internal/gitaly/hook/sidechannel.go
@@ -107,7 +107,10 @@ func (wt *SidechannelWaiter) run(callback func(*net.UnixConn) error) {
if err != nil {
return err
}
- defer c.Close()
+ defer func() {
+ // Error is already checked below.
+ _ = c.Close()
+ }()
// Eagerly remove the socket directory, in case the process exits before
// wt.Close() can run.
@@ -115,7 +118,15 @@ func (wt *SidechannelWaiter) run(callback func(*net.UnixConn) error) {
return err
}
- return callback(c)
+ if err := callback(c); err != nil {
+ return err
+ }
+
+ if err := c.Close(); err != nil {
+ return err
+ }
+
+ return nil
}()
}
diff --git a/internal/gitaly/hook/sidechannel_test.go b/internal/gitaly/hook/sidechannel_test.go
index 243e0de09..0cba065c9 100644
--- a/internal/gitaly/hook/sidechannel_test.go
+++ b/internal/gitaly/hook/sidechannel_test.go
@@ -47,7 +47,7 @@ func testSidechannelWithRuntimeDir(t *testing.T, runtimeDir string) {
},
)
require.NoError(t, err)
- defer wt.Close()
+ defer testhelper.MustClose(t, wt)
require.DirExists(t, wt.socketDir)
@@ -85,7 +85,6 @@ func testSidechannelCleanupWithRuntimeDir(t *testing.T, runtimeDir string) {
func(c *net.UnixConn) error { return nil },
)
require.NoError(t, err)
- defer wt.Close()
require.DirExists(t, wt.socketDir)
_ = wt.Close()
diff --git a/internal/gitaly/linguist/language_stats.go b/internal/gitaly/linguist/language_stats.go
index e65a90c9a..cefa3b644 100644
--- a/internal/gitaly/linguist/language_stats.go
+++ b/internal/gitaly/linguist/language_stats.go
@@ -135,7 +135,10 @@ func (c *languageStats) save(repo *localrepo.Repo, commitID string) error {
}()
w := zlib.NewWriter(file)
- defer w.Close()
+ defer func() {
+ // We already check the error further down.
+ _ = w.Close()
+ }()
if err = json.NewEncoder(w).Encode(c); err != nil {
return fmt.Errorf("languageStats encode json: %w", err)
diff --git a/internal/gitaly/server/auth_test.go b/internal/gitaly/server/auth_test.go
index 7cd8d9efa..a997282cb 100644
--- a/internal/gitaly/server/auth_test.go
+++ b/internal/gitaly/server/auth_test.go
@@ -225,7 +225,7 @@ func runServer(t *testing.T, cfg config.Cfg) string {
listener, err := net.Listen("unix", serverSocketPath)
require.NoError(t, err)
t.Cleanup(srv.Stop)
- go srv.Serve(listener)
+ go testhelper.MustServe(t, srv, listener)
return "unix://" + serverSocketPath
}
@@ -256,7 +256,7 @@ func runSecureServer(t *testing.T, cfg config.Cfg) string {
listener, hostPort := testhelper.GetLocalhostListener(t)
t.Cleanup(srv.Stop)
- go srv.Serve(listener)
+ go testhelper.MustServe(t, srv, listener)
return hostPort
}
diff --git a/internal/gitaly/server/server_factory_test.go b/internal/gitaly/server/server_factory_test.go
index 9a181089d..0137b62a5 100644
--- a/internal/gitaly/server/server_factory_test.go
+++ b/internal/gitaly/server/server_factory_test.go
@@ -44,6 +44,8 @@ func TestGitalyServerFactory(t *testing.T) {
if schema == starter.TLS {
srv, err := sf.CreateExternal(true)
require.NoError(t, err)
+ t.Cleanup(srv.Stop)
+
healthpb.RegisterHealthServer(srv, health.NewServer())
listener, err := net.Listen(starter.TCP, addr)
@@ -66,6 +68,8 @@ func TestGitalyServerFactory(t *testing.T) {
} else {
srv, err := sf.CreateExternal(false)
require.NoError(t, err)
+ t.Cleanup(srv.Stop)
+
healthpb.RegisterHealthServer(srv, health.NewServer())
listener, err := net.Listen(schema, addr)
@@ -299,7 +303,7 @@ func TestGitalyServerFactory_closeOrder(t *testing.T) {
require.NoError(t, err)
defer ln.Close()
- go server.Serve(ln)
+ go testhelper.MustServe(t, server, ln)
conn, err := grpc.DialContext(ctx, ln.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials()))
require.NoError(t, err)
diff --git a/internal/gitaly/service/hook/pack_objects_test.go b/internal/gitaly/service/hook/pack_objects_test.go
index 0bf4262da..403f3fe77 100644
--- a/internal/gitaly/service/hook/pack_objects_test.go
+++ b/internal/gitaly/service/hook/pack_objects_test.go
@@ -134,7 +134,7 @@ func testServerPackObjectsHookSeparateContextWithRuntimeDir(t *testing.T, ctx co
},
)
require.NoError(t, err)
- defer wt1.Close()
+ defer testhelper.MustClose(t, wt1)
go func() {
defer wg.Done()
@@ -174,7 +174,7 @@ func testServerPackObjectsHookSeparateContextWithRuntimeDir(t *testing.T, ctx co
},
)
require.NoError(t, err)
- defer wt2.Close()
+ defer testhelper.MustClose(t, wt2)
go func() {
defer wg.Done()
@@ -240,7 +240,7 @@ func testServerPackObjectsHookUsesCache(t *testing.T, ctx context.Context, runti
},
)
require.NoError(t, err)
- defer wt.Close()
+ defer testhelper.MustClose(t, wt)
client, conn := newHooksClient(t, cfg.SocketPath)
defer conn.Close()
@@ -346,7 +346,7 @@ func testServerPackObjectsHookWithSidechannelWithRuntimeDir(t *testing.T, ctx co
},
)
require.NoError(t, err)
- defer wt.Close()
+ defer testhelper.MustClose(t, wt)
client, conn := newHooksClient(t, cfg.SocketPath)
defer conn.Close()
@@ -539,7 +539,7 @@ func testServerPackObjectsHookWithSidechannelCanceledWithRuntimeDir(t *testing.T
},
)
require.NoError(t, err)
- defer wt.Close()
+ defer testhelper.MustClose(t, wt)
cfg.SocketPath = runHooksServer(t, cfg, nil)
repo, _ := gittest.CreateRepository(ctx, t, cfg, gittest.CreateRepositoryConfig{
diff --git a/internal/gitaly/service/repository/apply_gitattributes.go b/internal/gitaly/service/repository/apply_gitattributes.go
index 460a86ba5..700b2b6c2 100644
--- a/internal/gitaly/service/repository/apply_gitattributes.go
+++ b/internal/gitaly/service/repository/apply_gitattributes.go
@@ -22,7 +22,7 @@ import (
const attributesFileMode os.FileMode = 0o644
-func (s *server) applyGitattributes(ctx context.Context, repo *localrepo.Repo, objectReader catfile.ObjectReader, repoPath string, revision []byte) error {
+func (s *server) applyGitattributes(ctx context.Context, repo *localrepo.Repo, objectReader catfile.ObjectReader, repoPath string, revision []byte) (returnedErr error) {
infoPath := filepath.Join(repoPath, "info")
attributesPath := filepath.Join(infoPath, "attributes")
@@ -85,7 +85,13 @@ func (s *server) applyGitattributes(ctx context.Context, repo *localrepo.Repo, o
if err != nil {
return fmt.Errorf("creating gitattributes writer: %w", err)
}
- defer writer.Close()
+ defer func() {
+ if err := writer.Close(); err != nil && returnedErr == nil {
+ if !errors.Is(err, safe.ErrAlreadyDone) {
+ returnedErr = err
+ }
+ }
+ }()
if _, err := io.Copy(writer, blobObj); err != nil {
return err
diff --git a/internal/gitaly/service/smarthttp/upload_pack_test.go b/internal/gitaly/service/smarthttp/upload_pack_test.go
index 02ca6296e..1da5527da 100644
--- a/internal/gitaly/service/smarthttp/upload_pack_test.go
+++ b/internal/gitaly/service/smarthttp/upload_pack_test.go
@@ -6,6 +6,7 @@ import (
"bytes"
"context"
"encoding/binary"
+ "errors"
"fmt"
"io"
"path/filepath"
@@ -613,7 +614,6 @@ func makePostUploadPackWithSidechannelRequest(ctx context.Context, t *testing.T,
return <-errC
})
- defer waiter.Close()
rpcRequest := &gitalypb.PostUploadPackWithSidechannelRequest{
Repository: in.GetRepository(),
@@ -622,7 +622,11 @@ func makePostUploadPackWithSidechannelRequest(ctx context.Context, t *testing.T,
}
_, err := client.PostUploadPackWithSidechannel(ctxOut, rpcRequest)
if err == nil {
- require.NoError(t, waiter.Close())
+ testhelper.MustClose(t, waiter)
+ } else if err := waiter.Close(); err != nil && !errors.Is(err, sidechannel.ErrCallbackDidNotRun) {
+ // When the request failed the sidechannel may not even have been used, so we need
+ // to catch the `ErrCallbackDidNotRun` error here.
+ require.NoError(t, err)
}
return responseBuffer, err
diff --git a/internal/gitaly/storage/metadata.go b/internal/gitaly/storage/metadata.go
index 1af49493c..f5d8e51e9 100644
--- a/internal/gitaly/storage/metadata.go
+++ b/internal/gitaly/storage/metadata.go
@@ -2,6 +2,7 @@ package storage
import (
"encoding/json"
+ "errors"
"os"
"path/filepath"
@@ -21,7 +22,7 @@ type Metadata struct {
}
// WriteMetadataFile marshals and writes a metadata file
-func WriteMetadataFile(storagePath string) error {
+func WriteMetadataFile(storagePath string) (returnedErr error) {
path := filepath.Join(storagePath, metadataFilename)
if _, err := os.Stat(path); !os.IsNotExist(err) {
@@ -32,7 +33,13 @@ func WriteMetadataFile(storagePath string) error {
if err != nil {
return err
}
- defer fw.Close()
+ defer func() {
+ if err := fw.Close(); err != nil && returnedErr == nil {
+ if !errors.Is(err, safe.ErrAlreadyDone) {
+ returnedErr = err
+ }
+ }
+ }()
if err = json.NewEncoder(fw).Encode(&Metadata{
GitalyFilesystemID: uuid.New().String(),
diff --git a/internal/gitlab/test_server.go b/internal/gitlab/test_server.go
index b23e4b251..3a6a78eb0 100644
--- a/internal/gitlab/test_server.go
+++ b/internal/gitlab/test_server.go
@@ -569,7 +569,7 @@ func startSocketHTTPServer(tb testing.TB, mux *http.ServeMux, tlsCfg *tls.Config
TLSConfig: tlsCfg,
}
- go server.Serve(socketListener)
+ go testhelper.MustServe(tb, &server, socketListener)
url := "http+unix://" + filename
cleanup := func() {
diff --git a/internal/helper/chunk/chunker_test.go b/internal/helper/chunk/chunker_test.go
index ea759312e..e80be6419 100644
--- a/internal/helper/chunk/chunker_test.go
+++ b/internal/helper/chunk/chunker_test.go
@@ -85,7 +85,7 @@ func runServer(t *testing.T, s *server, opt ...grpc.ServerOption) (*grpc.Server,
lis, err := net.Listen("unix", serverSocketPath)
require.NoError(t, err)
- go grpcServer.Serve(lis)
+ go testhelper.MustServe(t, grpcServer, lis)
return grpcServer, "unix://" + serverSocketPath
}
diff --git a/internal/middleware/limithandler/middleware_test.go b/internal/middleware/limithandler/middleware_test.go
index d5aa4ee57..08c3f0cca 100644
--- a/internal/middleware/limithandler/middleware_test.go
+++ b/internal/middleware/limithandler/middleware_test.go
@@ -572,7 +572,7 @@ func runServer(t *testing.T, s pb.TestServer, opt ...grpc.ServerOption) (*grpc.S
lis, err := net.Listen("unix", serverSocketPath)
require.NoError(t, err)
- go grpcServer.Serve(lis)
+ go testhelper.MustServe(t, grpcServer, lis)
return grpcServer, "unix://" + serverSocketPath
}
diff --git a/internal/praefect/auth_test.go b/internal/praefect/auth_test.go
index 9f0cd9012..324392dce 100644
--- a/internal/praefect/auth_test.go
+++ b/internal/praefect/auth_test.go
@@ -169,7 +169,7 @@ func runServer(t *testing.T, token string, required bool) (*grpc.Server, string,
listener, err := net.Listen("unix", serverSocketPath)
require.NoError(t, err)
- go srv.Serve(listener)
+ go testhelper.MustServe(t, srv, listener)
return srv, "unix://" + serverSocketPath, cleanup
}
diff --git a/internal/praefect/delete_object_pool_test.go b/internal/praefect/delete_object_pool_test.go
index db63edddf..5e29bf0b1 100644
--- a/internal/praefect/delete_object_pool_test.go
+++ b/internal/praefect/delete_object_pool_test.go
@@ -45,10 +45,10 @@ func TestDeleteObjectPoolHandler(t *testing.T) {
secondaryLn, secondaryAddr := testhelper.GetLocalhostListener(t)
defer primarySrv.Stop()
- go primarySrv.Serve(primaryLn)
+ go testhelper.MustServe(t, primarySrv, primaryLn)
defer secondarySrv.Stop()
- go secondarySrv.Serve(secondaryLn)
+ go testhelper.MustServe(t, secondarySrv, secondaryLn)
db := testdb.New(t)
rs := datastore.NewPostgresRepositoryStore(db, nil)
@@ -96,7 +96,7 @@ func TestDeleteObjectPoolHandler(t *testing.T) {
}, struct{}{})
defer praefectSrv.Stop()
- go praefectSrv.Serve(praefectLn)
+ go testhelper.MustServe(t, praefectSrv, praefectLn)
praefectConn, err := grpc.Dial(praefectAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
require.NoError(t, err)
diff --git a/internal/praefect/grpc-proxy/proxy/handler_ext_test.go b/internal/praefect/grpc-proxy/proxy/handler_ext_test.go
index 7e5234fcd..a20131ca5 100644
--- a/internal/praefect/grpc-proxy/proxy/handler_ext_test.go
+++ b/internal/praefect/grpc-proxy/proxy/handler_ext_test.go
@@ -344,7 +344,7 @@ func TestProxyErrorPropagation(t *testing.T) {
backendServer := grpc.NewServer(grpc.UnknownServiceHandler(func(interface{}, grpc.ServerStream) error {
return tc.backendError
}))
- go func() { backendServer.Serve(backendListener) }()
+ go testhelper.MustServe(t, backendServer, backendListener)
defer backendServer.Stop()
ctx := testhelper.Context(t)
@@ -374,7 +374,7 @@ func TestProxyErrorPropagation(t *testing.T) {
})),
)
- go func() { proxyServer.Serve(proxyListener) }()
+ go testhelper.MustServe(t, proxyServer, proxyListener)
defer proxyServer.Stop()
proxyClientConn, err := grpc.DialContext(ctx, "unix://"+proxyListener.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials()))
@@ -488,7 +488,7 @@ func TestRegisterStreamHandlers(t *testing.T) {
proxy.RegisterStreamHandlers(server, grpc_testing.TestService_ServiceDesc.ServiceName, registeredHandlers)
listener := newListener(t)
- go server.Serve(listener)
+ go testhelper.MustServe(t, server, listener)
defer server.Stop()
conn, err := client.Dial("tcp://"+listener.Addr().String(), []grpc.DialOption{grpc.WithBlock()})
diff --git a/internal/praefect/grpc-proxy/proxy/testhelper_test.go b/internal/praefect/grpc-proxy/proxy/testhelper_test.go
index bc7ffca5e..4a8dd5aa0 100644
--- a/internal/praefect/grpc-proxy/proxy/testhelper_test.go
+++ b/internal/praefect/grpc-proxy/proxy/testhelper_test.go
@@ -41,7 +41,7 @@ func newBackendPinger(tb testing.TB, ctx context.Context) (*grpc.ClientConn, *in
done := make(chan struct{})
go func() {
defer close(done)
- srvr.Serve(listener)
+ require.NoError(tb, srvr.Serve(listener))
}()
cc, err := grpc.DialContext(
@@ -83,7 +83,7 @@ func newProxy(tb testing.TB, ctx context.Context, director proxy.StreamDirector,
listener := newListener(tb)
go func() {
defer close(done)
- proxySrvr.Serve(listener)
+ require.NoError(tb, proxySrvr.Serve(listener))
}()
proxyCC, err := grpc.DialContext(
diff --git a/internal/praefect/middleware/errorhandler_test.go b/internal/praefect/middleware/errorhandler_test.go
index 9e221e741..e87015a6c 100644
--- a/internal/praefect/middleware/errorhandler_test.go
+++ b/internal/praefect/middleware/errorhandler_test.go
@@ -64,7 +64,7 @@ func TestStreamInterceptor(t *testing.T) {
mock.RegisterSimpleServiceServer(internalSrv, &simpleService{})
- go internalSrv.Serve(lis)
+ go testhelper.MustServe(t, internalSrv, lis)
defer internalSrv.Stop()
srvOptions := []grpc.ServerOption{
@@ -92,7 +92,7 @@ func TestStreamInterceptor(t *testing.T) {
praefectSrv := grpc.NewServer(srvOptions...)
defer praefectSrv.Stop()
- go praefectSrv.Serve(praefectLis)
+ go testhelper.MustServe(t, praefectSrv, praefectLis)
praefectCC, err := grpc.Dial("unix://"+praefectSocket, grpc.WithTransportCredentials(insecure.NewCredentials()))
defer testhelper.MustClose(t, praefectCC)
diff --git a/internal/praefect/node_test.go b/internal/praefect/node_test.go
index b9a4bfecc..452a13d1a 100644
--- a/internal/praefect/node_test.go
+++ b/internal/praefect/node_test.go
@@ -54,7 +54,7 @@ func TestDialNodes(t *testing.T) {
srv := grpc.NewServer()
grpc_health_v1.RegisterHealthServer(srv, healthSrv)
defer srv.Stop()
- go srv.Serve(ln)
+ go testhelper.MustServe(t, srv, ln)
cfgNodes = append(cfgNodes, &config.Node{
Storage: n.storage,
diff --git a/internal/praefect/nodes/sql_elector_test.go b/internal/praefect/nodes/sql_elector_test.go
index b2c90ac21..adc79cb75 100644
--- a/internal/praefect/nodes/sql_elector_test.go
+++ b/internal/praefect/nodes/sql_elector_test.go
@@ -453,7 +453,7 @@ func TestConnectionMultiplexing(t *testing.T) {
ln, err := net.Listen("tcp", "localhost:0")
require.NoError(t, err)
- go srv.Serve(ln)
+ go testhelper.MustServe(t, srv, ln)
db := testdb.New(t)
mgr, err := NewManager(
diff --git a/internal/praefect/remove_repository_test.go b/internal/praefect/remove_repository_test.go
index f9eaf057a..4d8917378 100644
--- a/internal/praefect/remove_repository_test.go
+++ b/internal/praefect/remove_repository_test.go
@@ -124,7 +124,7 @@ func TestRemoveRepositoryHandler(t *testing.T) {
)
defer srv.Stop()
- go func() { srv.Serve(ln) }()
+ go testhelper.MustServe(t, srv, ln)
clientConn, err := grpc.DialContext(ctx, "unix:"+ln.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials()))
require.NoError(t, err)
diff --git a/internal/praefect/replicator_pg_test.go b/internal/praefect/replicator_pg_test.go
index 4bd66365e..2ee5ef568 100644
--- a/internal/praefect/replicator_pg_test.go
+++ b/internal/praefect/replicator_pg_test.go
@@ -45,7 +45,7 @@ func TestReplicatorInvalidSourceRepository(t *testing.T) {
},
})
defer srv.Stop()
- go srv.Serve(ln)
+ go testhelper.MustServe(t, srv, ln)
targetCC, err := client.Dial(ln.Addr().Network()+":"+ln.Addr().String(), nil)
require.NoError(t, err)
@@ -101,7 +101,7 @@ func TestReplicatorDestroy(t *testing.T) {
return stream.SendMsg(&gitalypb.RemoveRepositoryResponse{})
}))
- go srv.Serve(ln)
+ go testhelper.MustServe(t, srv, ln)
defer srv.Stop()
clientConn, err := grpc.Dial(ln.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials()))
diff --git a/internal/praefect/repository_exists_test.go b/internal/praefect/repository_exists_test.go
index 3eb445e7e..ba005cc84 100644
--- a/internal/praefect/repository_exists_test.go
+++ b/internal/praefect/repository_exists_test.go
@@ -103,7 +103,7 @@ func TestRepositoryExistsHandler(t *testing.T) {
)
defer srv.Stop()
- go func() { srv.Serve(ln) }()
+ go testhelper.MustServe(t, srv, ln)
clientConn, err := grpc.DialContext(ctx, "unix://"+ln.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials()))
require.NoError(t, err)
diff --git a/internal/praefect/server_factory_test.go b/internal/praefect/server_factory_test.go
index 7fd850e21..bd3147d02 100644
--- a/internal/praefect/server_factory_test.go
+++ b/internal/praefect/server_factory_test.go
@@ -165,7 +165,7 @@ func TestServerFactory(t *testing.T) {
return nil
})
- defer waiter.Close()
+ defer testhelper.MustClose(t, waiter)
_, err = gitalypb.NewSmartHTTPServiceClient(cc).PostUploadPackWithSidechannel(ctx,
&gitalypb.PostUploadPackWithSidechannelRequest{Repository: repo},
@@ -184,9 +184,8 @@ func TestServerFactory(t *testing.T) {
listener, err := net.Listen(starter.TCP, "localhost:0")
require.NoError(t, err)
- defer func() { require.NoError(t, listener.Close()) }()
- go praefectServerFactory.Serve(listener, false)
+ go func() { require.NoError(t, praefectServerFactory.Serve(listener, false)) }()
praefectAddr, err := starter.ComposeEndpoint(listener.Addr().Network(), listener.Addr().String())
require.NoError(t, err)
@@ -217,9 +216,8 @@ func TestServerFactory(t *testing.T) {
listener, err := net.Listen(starter.TCP, "localhost:0")
require.NoError(t, err)
- defer func() { require.NoError(t, listener.Close()) }()
- go praefectServerFactory.Serve(listener, true)
+ go func() { require.NoError(t, praefectServerFactory.Serve(listener, true)) }()
ctx := testhelper.Context(t)
certPool, err := x509.SystemCertPool()
@@ -260,9 +258,8 @@ func TestServerFactory(t *testing.T) {
// start with tcp address
tcpListener, err := net.Listen(starter.TCP, "localhost:0")
require.NoError(t, err)
- defer tcpListener.Close()
- go praefectServerFactory.Serve(tcpListener, false)
+ go func() { require.NoError(t, praefectServerFactory.Serve(tcpListener, false)) }()
praefectTCPAddr, err := starter.ComposeEndpoint(tcpListener.Addr().Network(), tcpListener.Addr().String())
require.NoError(t, err)
@@ -276,9 +273,8 @@ func TestServerFactory(t *testing.T) {
// start with tls address
tlsListener, err := net.Listen(starter.TCP, "localhost:0")
require.NoError(t, err)
- defer tlsListener.Close()
- go praefectServerFactory.Serve(tlsListener, true)
+ go func() { require.NoError(t, praefectServerFactory.Serve(tlsListener, true)) }()
praefectTLSAddr, err := starter.ComposeEndpoint(tcpListener.Addr().Network(), tcpListener.Addr().String())
require.NoError(t, err)
@@ -294,9 +290,8 @@ func TestServerFactory(t *testing.T) {
defer func() { require.NoError(t, os.RemoveAll(socketPath)) }()
socketListener, err := net.Listen(starter.Unix, socketPath)
require.NoError(t, err)
- defer socketListener.Close()
- go praefectServerFactory.Serve(socketListener, false)
+ go func() { require.NoError(t, praefectServerFactory.Serve(socketListener, false)) }()
praefectSocketAddr, err := starter.ComposeEndpoint(socketListener.Addr().Network(), socketListener.Addr().String())
require.NoError(t, err)
diff --git a/internal/praefect/server_test.go b/internal/praefect/server_test.go
index edbed63e0..15c69e35a 100644
--- a/internal/praefect/server_test.go
+++ b/internal/praefect/server_test.go
@@ -94,7 +94,7 @@ func TestNewBackchannelServerFactory(t *testing.T) {
ln, err := net.Listen("tcp", "localhost:0")
require.NoError(t, err)
- go server.Serve(ln)
+ go testhelper.MustServe(t, server, ln)
ctx := testhelper.Context(t)
nodeSet, err := DialNodes(ctx, []*config.VirtualStorage{{
@@ -848,7 +848,7 @@ func TestProxyWrites(t *testing.T) {
listener, err := net.Listen("unix", socket)
require.NoError(t, err)
- go server.Serve(listener)
+ go testhelper.MustServe(t, server, listener)
defer server.Stop()
client, _ := newSmartHTTPClient(t, "unix://"+socket)
@@ -1002,7 +1002,7 @@ func TestErrorThreshold(t *testing.T) {
listener, err := net.Listen("unix", socket)
require.NoError(t, err)
- go server.Serve(listener)
+ go testhelper.MustServe(t, server, listener)
defer server.Stop()
conn, err := dial("unix://"+socket, []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())})
diff --git a/internal/sidechannel/proxy.go b/internal/sidechannel/proxy.go
index 6da61274f..ee92baebf 100644
--- a/internal/sidechannel/proxy.go
+++ b/internal/sidechannel/proxy.go
@@ -18,14 +18,19 @@ func NewUnaryProxy(registry *Registry) grpc.UnaryClientInterceptor {
}
ctx, waiter := RegisterSidechannel(ctx, registry, proxy(ctx))
- defer waiter.Close()
+ defer func() {
+ // We aleady check the error further down.
+ _ = waiter.Close()
+ }()
if err := invoker(ctx, method, req, reply, cc, opts...); err != nil {
return err
}
+
if err := waiter.Close(); err != nil && err != ErrCallbackDidNotRun {
return fmt.Errorf("sidechannel: proxy callback: %w", err)
}
+
return nil
}
}
diff --git a/internal/sidechannel/proxy_test.go b/internal/sidechannel/proxy_test.go
index ed2f3e2a8..398d9c780 100644
--- a/internal/sidechannel/proxy_test.go
+++ b/internal/sidechannel/proxy_test.go
@@ -169,7 +169,7 @@ func testStreamProxy(t *testing.T, closeWrite bool) {
conn, registry := dial(t, proxyAddr)
ctx, waiter := RegisterSidechannel(ctx, registry, testProxyClient(closeWrite))
- defer waiter.Close()
+ defer testhelper.MustClose(t, waiter)
client, err := gitalypb.NewSSHServiceClient(conn).SSHUploadPack(ctx)
require.NoError(t, err)
@@ -206,6 +206,6 @@ func startStreamServer(t *testing.T, handler func(gitalypb.SSHService_SSHUploadP
require.NoError(t, err)
t.Cleanup(srv.Stop)
- go srv.Serve(ln)
+ go testhelper.MustServe(t, srv, ln)
return ln.Addr().String()
}
diff --git a/internal/sidechannel/registry_test.go b/internal/sidechannel/registry_test.go
index 8a286b617..d1a37b927 100644
--- a/internal/sidechannel/registry_test.go
+++ b/internal/sidechannel/registry_test.go
@@ -13,6 +13,7 @@ import (
"testing"
"github.com/stretchr/testify/require"
+ "gitlab.com/gitlab-org/gitaly/v15/internal/testhelper"
)
func TestRegistry(t *testing.T) {
@@ -25,7 +26,7 @@ func TestRegistry(t *testing.T) {
<-triggerCallback
return nil
})
- defer waiter.Close()
+ defer testhelper.MustClose(t, waiter)
require.Equal(t, 1, registry.waiting())
@@ -57,7 +58,7 @@ func TestRegistry(t *testing.T) {
return conn.CloseWrite()
})
- defer waiter.Close()
+ defer testhelper.MustClose(t, waiter)
require.NoError(t, registry.receive(waiter.id, client))
require.NoError(t, waiter.Close())
diff --git a/internal/sidechannel/sidechannel_test.go b/internal/sidechannel/sidechannel_test.go
index 7043e1642..b07031323 100644
--- a/internal/sidechannel/sidechannel_test.go
+++ b/internal/sidechannel/sidechannel_test.go
@@ -157,16 +157,15 @@ func startServer(t *testing.T, th testHandler, opts ...grpc.ServerOption) string
opts = append(opts, grpc.Creds(lm))
s := grpc.NewServer(opts...)
- t.Cleanup(func() { s.Stop() })
+ t.Cleanup(s.Stop)
handler := &server{testHandler: th}
healthpb.RegisterHealthServer(s, handler)
lis, err := net.Listen("tcp", "localhost:0")
require.NoError(t, err)
- t.Cleanup(func() { lis.Close() })
- go func() { s.Serve(lis) }()
+ go testhelper.MustServe(t, s, lis)
return lis.Addr().String()
}
@@ -187,7 +186,10 @@ func call(ctx context.Context, conn *grpc.ClientConn, registry *Registry, handle
client := healthpb.NewHealthClient(conn)
ctxOut, waiter := RegisterSidechannel(ctx, registry, handler)
- defer waiter.Close()
+ defer func() {
+ // We aleady check the error further down.
+ _ = waiter.Close()
+ }()
if _, err := client.Check(ctxOut, &healthpb.HealthCheckRequest{}); err != nil {
return err
diff --git a/internal/testhelper/testhelper.go b/internal/testhelper/testhelper.go
index 44f691452..02440e7f0 100644
--- a/internal/testhelper/testhelper.go
+++ b/internal/testhelper/testhelper.go
@@ -8,11 +8,13 @@ import (
"crypto/rand"
"crypto/x509"
"encoding/pem"
+ "errors"
"fmt"
"io"
"math/big"
mrand "math/rand"
"net"
+ "net/http"
"os"
"os/exec"
"path/filepath"
@@ -102,6 +104,25 @@ func MustClose(tb testing.TB, closer io.Closer) {
require.NoError(tb, closer.Close())
}
+// Server is an interface for a server that can serve requests on a specific listener. This
+// interface is used by the MustServe helper function.
+type Server interface {
+ Serve(net.Listener) error
+}
+
+// MustServe starts to serve the given server with the listener. This function asserts that the
+// server was able to successfully serve and is useful in contexts where one wants to simply spawn a
+// server in a Goroutine.
+func MustServe(tb testing.TB, server Server, listener net.Listener) {
+ tb.Helper()
+
+ // `http.Server.Serve()` is expected to return `http.ErrServerClosed`, so we special-case
+ // this error here.
+ if err := server.Serve(listener); err != nil && !errors.Is(err, http.ErrServerClosed) {
+ require.NoError(tb, err)
+ }
+}
+
// CopyFile copies a file at the path src to a file at the path dst
func CopyFile(tb testing.TB, src, dst string) {
fsrc, err := os.Open(src)
diff --git a/packed_binaries.go b/packed_binaries.go
index fe3e435e0..6b0774988 100644
--- a/packed_binaries.go
+++ b/packed_binaries.go
@@ -40,14 +40,20 @@ func UnpackAuxiliaryBinaries(destinationDir string) error {
if err != nil {
return fmt.Errorf("open packed binary %q: %w", packedPath, err)
}
- defer packedFile.Close()
+ defer func() {
+ // We already check the error below.
+ _ = packedFile.Close()
+ }()
unpackedPath := filepath.Join(destinationDir, entry.Name())
unpackedFile, err := os.OpenFile(unpackedPath, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0o700)
if err != nil {
return err
}
- defer unpackedFile.Close()
+ defer func() {
+ // We already check the error below.
+ _ = unpackedFile.Close()
+ }()
if _, err := io.Copy(unpackedFile, packedFile); err != nil {
return fmt.Errorf("unpack %q: %w", unpackedPath, err)
@@ -57,6 +63,10 @@ func UnpackAuxiliaryBinaries(destinationDir string) error {
return fmt.Errorf("close %q: %w", unpackedPath, err)
}
+ if err := packedFile.Close(); err != nil {
+ return fmt.Errorf("close packed file %q: %w", packedPath, err)
+ }
+
return nil
}(); err != nil {
return err