Skip to content
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions dialer.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"strings"
"sync"
"sync/atomic"
"syscall"
"time"

"cloud.google.com/go/cloudsqlconn/errtype"
Expand Down Expand Up @@ -230,7 +231,7 @@ func (d *Dialer) Dial(ctx context.Context, instance string, opts ...DialOption)
trace.RecordDialLatency(ctx, instance, d.dialerID, latency)
}()

return newInstrumentedConn(tlsConn, func() {
return newInstrumentedConn(conn, tlsConn, func() {
n := atomic.AddUint64(&i.OpenConns, ^uint64(0))
trace.RecordOpenConnections(context.Background(), int64(n), d.dialerID, i.String())
}), nil
Expand Down Expand Up @@ -264,9 +265,10 @@ func (d *Dialer) Warmup(ctx context.Context, instance string, opts ...DialOption

// newInstrumentedConn initializes an instrumentedConn that on closing will
// decrement the number of open connects and record the result.
func newInstrumentedConn(conn net.Conn, closeFunc func()) *instrumentedConn {
func newInstrumentedConn(rawConn, conn net.Conn, closeFunc func()) *instrumentedConn {
return &instrumentedConn{
Conn: conn,
rawConn: rawConn,
closeFunc: closeFunc,
}
}
Expand All @@ -275,9 +277,18 @@ func newInstrumentedConn(conn net.Conn, closeFunc func()) *instrumentedConn {
// is closed.
type instrumentedConn struct {
net.Conn
// rawConn is the underlying net.Conn without TLS
rawConn net.Conn
closeFunc func()
}

// SyscallConn supports a connection check in the MySQL driver by delegating to
// the underlying non-TLS net.Conn.
func (i *instrumentedConn) SyscallConn() (syscall.RawConn, error) {
sconn := i.rawConn.(syscall.Conn)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will this break on windows?

Copy link
Member Author

@enocom enocom Jun 14, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question. I'll add a unit test to make sure we have support in either case.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like the MySQL driver doesn't have support for Windows here: https://github.com/go-sql-driver/mysql/blob/ad9fa14acdcf7d0533e7fbe58728f3d216213ade/conncheck_dummy.go#L9. What would your expectation be?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated this so it won't panic if the type assertion fails. Separately, this builds on Windows with the unit test, so I think we're good.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would just expect it not to panic. (Parity to go mysql should be good)

humm I don't think returning an error will work with go mysql's current implementation. it will always trigger driver.ErrBadConn.

func (mc *mysqlConn) writePacket(data []byte) error {
	...
		if err == nil && mc.cfg.CheckConnLiveness {
			err = connCheck(conn)
		}
		if err != nil {
			errLog.Print("closing bad idle connection: ", err)
			mc.Close()
			return driver.ErrBadConn
		}
         ...

where connCheck():

func connCheck(conn net.Conn) error {
	...
	rawConn, err := sysConn.SyscallConn()
	if err != nil {
		return err
	}
	...
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll take another look at this and see what we can do. Thanks for all your help on this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like the platforms that don't support the call won't use connCheck: https://github.com/go-sql-driver/mysql/blob/ad9fa14acdcf7d0533e7fbe58728f3d216213ade/conncheck_dummy.go#L16

So it seems like it's probably fine to return an error, since if it is being used something probably wrong?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That’s my understanding as well. @Gentoli what do you think?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I did not realize // +build is built-in to golang. Both with or without the check on the cast should work.

return sconn.SyscallConn()
}

// Close delegates to the underylying net.Conn interface and reports the close
// to the provided closeFunc only when Close returns no error.
func (i *instrumentedConn) Close() error {
Expand Down