summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Drozdov <idrozdov@gitlab.com>2022-05-16 01:32:07 +0400
committerIgor Drozdov <idrozdov@gitlab.com>2022-05-17 08:17:47 +0400
commitc05ed91ea824ce015f51417196021b7e8a5837d0 (patch)
treef931815591e9cbaca48e97dcef6a2a493b54e4e0
parenta77babe96fac9c880061fa63fffabfc8406f11bf (diff)
downloadgitlab-shell-c05ed91ea824ce015f51417196021b7e8a5837d0.tar.gz
Wait until all Gitaly sessions are executed
If they haven't been executed within a timeout, we unblock the execution. Issue: https://gitlab.com/gitlab-org/gitlab-shell/-/issues/563 We have an issue when a lot of git clones operations get canceled. It was assumed that some clients close the connection just after all the data has been received from Git server. If there was a network delay and gitlab-sshd hadn't managed to gracefully close the connection, context get canceled and Gitaly cancels the execution and returns the error. Let's wait for a perion to allow Gitaly to gracefully complete the operation
-rw-r--r--internal/sshd/connection.go16
-rw-r--r--internal/sshd/connection_test.go5
2 files changed, 15 insertions, 6 deletions
diff --git a/internal/sshd/connection.go b/internal/sshd/connection.go
index 060156d..ebb4fe0 100644
--- a/internal/sshd/connection.go
+++ b/internal/sshd/connection.go
@@ -15,19 +15,25 @@ import (
const KeepAliveMsg = "keepalive@openssh.com"
+var EOFTimeout = 10 * time.Second
+
type connection struct {
cfg *config.Config
concurrentSessions *semaphore.Weighted
remoteAddr string
sconn *ssh.ServerConn
+ maxSessions int64
}
type channelHandler func(context.Context, ssh.Channel, <-chan *ssh.Request) error
func newConnection(cfg *config.Config, remoteAddr string, sconn *ssh.ServerConn) *connection {
+ maxSessions := cfg.Server.ConcurrentSessionsLimit
+
return &connection{
cfg: cfg,
- concurrentSessions: semaphore.NewWeighted(cfg.Server.ConcurrentSessionsLimit),
+ maxSessions: maxSessions,
+ concurrentSessions: semaphore.NewWeighted(maxSessions),
remoteAddr: remoteAddr,
sconn: sconn,
}
@@ -85,6 +91,14 @@ func (c *connection) handle(ctx context.Context, chans <-chan ssh.NewChannel, ha
ctxlog.Info("connection: handle: done")
}()
}
+
+ // When a connection has been prematurely closed we block execution until all concurrent sessions are released
+ // in order to allow Gitaly complete the operations and close all the channels gracefully.
+ // If it didn't happen within timeout, we unblock the execution
+ // Related issue: https://gitlab.com/gitlab-org/gitlab-shell/-/issues/563
+ ctx, cancel := context.WithTimeout(ctx, EOFTimeout)
+ defer cancel()
+ c.concurrentSessions.Acquire(ctx, c.maxSessions)
}
func (c *connection) sendKeepAliveMsg(ctx context.Context, ticker *time.Ticker) {
diff --git a/internal/sshd/connection_test.go b/internal/sshd/connection_test.go
index 0a06255..d3a2287 100644
--- a/internal/sshd/connection_test.go
+++ b/internal/sshd/connection_test.go
@@ -55,14 +55,9 @@ type fakeConn struct {
ssh.Conn
sentRequestName string
- waitErr error
mu sync.Mutex
}
-func (f *fakeConn) Wait() error {
- return f.waitErr
-}
-
func (f *fakeConn) SentRequestName() string {
f.mu.Lock()
defer f.mu.Unlock()