diff --git a/pkg/git/libgit2/managed/ssh.go b/pkg/git/libgit2/managed/ssh.go index 8e0712743..1be9ccd33 100644 --- a/pkg/git/libgit2/managed/ssh.go +++ b/pkg/git/libgit2/managed/ssh.go @@ -53,6 +53,7 @@ import ( "net/url" "runtime" "strings" + "time" "golang.org/x/crypto/ssh" @@ -214,14 +215,40 @@ func (t *sshSmartSubtransport) Action(urlString string, action git2go.SmartServi } func (t *sshSmartSubtransport) Close() error { + var returnErr error t.currentStream = nil if t.client != nil { - t.stdin.Close() - t.session.Wait() - t.session.Close() + if err := t.stdin.Close(); err != nil { + returnErr = fmt.Errorf("cannot close stdin: %w", err) + } t.client = nil } - return nil + if t.session != nil { + + // In some scenarios session.Wait() can hang indefinitely. + // Here we force a timeout to skip the wait and continue + // with closing the session. + done := make(chan error, 1) + go func() { + err := t.session.Wait() + done <- err + }() + + select { + case doneErr := <-done: + if doneErr != nil { + returnErr = fmt.Errorf("cannot wait session: %w", doneErr) + } + case <-time.After(5 * time.Second): + returnErr = fmt.Errorf("timed out waiting for session.Wait()") + } + + if err := t.session.Close(); err != nil { + returnErr = fmt.Errorf("cannot close session: %w", err) + } + } + + return returnErr } func (t *sshSmartSubtransport) Free() {