Skip to content

Data race warning #117

Open
Open
@krostar

Description

@krostar

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

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions