@@ -54,6 +54,7 @@ import (
54
54
"runtime"
55
55
"strings"
56
56
"sync"
57
+ "sync/atomic"
57
58
"time"
58
59
59
60
"golang.org/x/crypto/ssh"
@@ -80,10 +81,12 @@ func registerManagedSSH() error {
80
81
}
81
82
82
83
func sshSmartSubtransportFactory (remote * git2go.Remote , transport * git2go.Transport ) (git2go.SmartSubtransport , error ) {
84
+ var closed int32 = 0
83
85
return & sshSmartSubtransport {
84
- transport : transport ,
85
- ctx : context .Background (),
86
- logger : logr .Discard (),
86
+ transport : transport ,
87
+ ctx : context .Background (),
88
+ logger : logr .Discard (),
89
+ closedSessions : & closed ,
87
90
}, nil
88
91
}
89
92
@@ -109,6 +112,8 @@ type sshSmartSubtransport struct {
109
112
stdin io.WriteCloser
110
113
stdout io.Reader
111
114
115
+ closedSessions * int32
116
+
112
117
con connection
113
118
}
114
119
@@ -117,7 +122,6 @@ type connection struct {
117
122
session * ssh.Session
118
123
currentStream * sshSmartSubtransportStream
119
124
connected bool
120
- m sync.RWMutex
121
125
}
122
126
123
127
func (t * sshSmartSubtransport ) Action (transportOptionsURL string , action git2go.SmartServiceAction ) (git2go.SmartSubtransportStream , error ) {
@@ -208,13 +212,11 @@ func (t *sshSmartSubtransport) Action(transportOptionsURL string, action git2go.
208
212
return nil
209
213
}
210
214
211
- t .con .m .RLock ()
212
- if t .con .connected == true {
215
+ if t .con .connected {
213
216
// The connection is no longer shared across actions, so ensures
214
217
// all has been released before starting a new connection.
215
218
_ = t .Close ()
216
219
}
217
- t .con .m .RUnlock ()
218
220
219
221
err = t .createConn (addr , sshConfig )
220
222
if err != nil {
@@ -251,7 +253,6 @@ func (t *sshSmartSubtransport) Action(transportOptionsURL string, action git2go.
251
253
"recovered from libgit2 ssh smart subtransport panic" )
252
254
}
253
255
}()
254
-
255
256
var cancel context.CancelFunc
256
257
ctx := t .ctx
257
258
@@ -261,19 +262,17 @@ func (t *sshSmartSubtransport) Action(transportOptionsURL string, action git2go.
261
262
defer cancel ()
262
263
}
263
264
265
+ closedAlready := atomic .LoadInt32 (t .closedSessions )
264
266
for {
265
267
select {
266
268
case <- ctx .Done ():
267
269
t .Close ()
268
270
return nil
269
271
270
272
default :
271
- t .con .m .RLock ()
272
- if ! t .con .connected {
273
- t .con .m .RUnlock ()
273
+ if atomic .LoadInt32 (t .closedSessions ) > closedAlready {
274
274
return nil
275
275
}
276
- t .con .m .RUnlock ()
277
276
278
277
_ , err := io .Copy (w , reader )
279
278
if err != nil {
@@ -311,10 +310,8 @@ func (t *sshSmartSubtransport) createConn(addr string, sshConfig *ssh.ClientConf
311
310
return err
312
311
}
313
312
314
- t .con .m .Lock ()
315
313
t .con .connected = true
316
314
t .con .client = ssh .NewClient (c , chans , reqs )
317
- t .con .m .Unlock ()
318
315
319
316
return nil
320
317
}
@@ -330,8 +327,6 @@ func (t *sshSmartSubtransport) createConn(addr string, sshConfig *ssh.ClientConf
330
327
// SmartSubTransport (i.e. unreleased resources, staled connections).
331
328
func (t * sshSmartSubtransport ) Close () error {
332
329
t .logger .V (logger .TraceLevel ).Info ("sshSmartSubtransport.Close()" )
333
- t .con .m .Lock ()
334
- defer t .con .m .Unlock ()
335
330
336
331
t .con .currentStream = nil
337
332
if t .con .client != nil && t .stdin != nil {
@@ -349,8 +344,10 @@ func (t *sshSmartSubtransport) Close() error {
349
344
_ = t .con .client .Close ()
350
345
t .logger .V (logger .TraceLevel ).Info ("close client" )
351
346
}
347
+ t .con .client = nil
352
348
353
349
t .con .connected = false
350
+ atomic .AddInt32 (t .closedSessions , 1 )
354
351
355
352
return nil
356
353
}
0 commit comments