Open
Description
Hello,
I'm using you awesome library to help testing something that creates a ssh client without relying on something installed on the host that execute the tests.
When testing, I got the following data race:
==================
WARNING: DATA RACE
Write at 0x00c0001680d8 by goroutine 38:
sync.(*WaitGroup).Wait()
/usr/local/go/src/internal/race/race.go:41 +0xef
github.com/gliderlabs/ssh.(*Server).Shutdown.func1()
/go/pkg/mod/github.com/gliderlabs/[email protected]/server.go:178 +0x55
Previous read at 0x00c0001680d8 by goroutine 25:
sync.(*WaitGroup).Add()
/usr/local/go/src/internal/race/race.go:37 +0x169
github.com/gliderlabs/ssh.(*Server).trackConn()
/go/pkg/mod/github.com/gliderlabs/[email protected]/server.go:389 +0x107
github.com/gliderlabs/ssh.(*Server).handleConn()
/go/pkg/mod/github.com/gliderlabs/[email protected]/server.go:259 +0x2c7
Goroutine 38 (running) created at:
github.com/gliderlabs/ssh.(*Server).Shutdown()
/go/pkg/mod/github.com/gliderlabs/[email protected]/server.go:176 +0xef
app/pkg/sshx.newSSHServer.func3()
/app/pkg/sshx/client_test.go:89 +0xd0
app/pkg/sshx.TestNewClient.func3()
/app/pkg/sshx/client_test.go:118 +0x39b
testing.tRunner()
/usr/local/go/src/testing/testing.go:865 +0x163
Goroutine 25 (running) created at:
github.com/gliderlabs/ssh.(*Server).Serve()
/go/pkg/mod/github.com/gliderlabs/[email protected]/server.go:230 +0x184
app/pkg/sshx.newSSHServer.func2()
/app/pkg/sshx/client_test.go:77 +0x59
==================
It happened only one time, and I didn't succeeds to reproduce as restarting the same test without touching anything make it PASS, and so far I didn't get this data race again.
Here is how I call your library:
func TestNewClient(t *testing.T) {
addr, stop, exited, err := newSSHServer()
require.NoError(t, err)
client, err := NewClient(addr) // GITHUB: this returns a *ssh.Client configured to hit the configured ssh server
require.NoError(t, err)
assert.Equal(t, "SSH-2.0-go-test_"+addr, string(client.ServerVersion())) // GITHUB: dumb test, just making sure we're connected on the server we wanted
assert.NoError(t, client.Close())
stop()
assert.NoError(t, <-exited)
}
func newSSHServer() (string, func(), <-chan error, error) {
listener, err := findFreeListener() // GITHUB: this helps to find a listener available
if err != nil {
return "", nil, nil, errors.Wrap(err, "unable to get free listener")
}
addr := listener.Addr().String()
srv := gssh.Server{
Addr: addr,
Version: "go-test_" + addr,
LocalPortForwardingCallback: func(gssh.Context, string, uint32) bool { return true },
ChannelHandlers: map[string]gssh.ChannelHandler{
"direct-tcpip": gssh.DirectTCPIPHandler,
},
}
cerr := make(chan error)
go func() {
if err := srv.Serve(listener); err != nil {
if errors.Cause(err) != gssh.ErrServerClosed {
cerr <- errors.Wrap(err, "unable to serve ssh")
}
}
cerr <- nil
}()
return addr, func() {
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
if err := srv.Shutdown(ctx); err != nil {
select {
case cerr <- err:
default:
}
}
}, cerr, nil
}
I'm not sure how critical this can be, nor why I got it only one time, but I wanted to notify you about this.
Thanks for your work on this library,
krostar
Metadata
Metadata
Assignees
Labels
No labels