Skip to content

Commit 903d9dc

Browse files
committed
conncheck: use unix.Poll instead of syscall.Read
1 parent 5d4a831 commit 903d9dc

File tree

4 files changed

+57
-32
lines changed

4 files changed

+57
-32
lines changed

Diff for: conncheck.go

+17-19
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,16 @@ package mysql
1313

1414
import (
1515
"errors"
16-
"io"
16+
"fmt"
1717
"net"
1818
"syscall"
19+
20+
"golang.org/x/sys/unix"
1921
)
2022

21-
var errUnexpectedRead = errors.New("unexpected read from socket")
23+
var errUnexpectedEvent = errors.New("recieved unexpected event")
2224

2325
func connCheck(conn net.Conn) error {
24-
var sysErr error
25-
2626
sysConn, ok := conn.(syscall.Conn)
2727
if !ok {
2828
return nil
@@ -32,24 +32,22 @@ func connCheck(conn net.Conn) error {
3232
return err
3333
}
3434

35-
err = rawConn.Read(func(fd uintptr) bool {
36-
var buf [1]byte
37-
n, err := syscall.Read(int(fd), buf[:])
38-
switch {
39-
case n == 0 && err == nil:
40-
sysErr = io.EOF
41-
case n > 0:
42-
sysErr = errUnexpectedRead
43-
case err == syscall.EAGAIN || err == syscall.EWOULDBLOCK:
44-
sysErr = nil
45-
default:
46-
sysErr = err
35+
var pollErr error
36+
err = rawConn.Control(func(fd uintptr) {
37+
fds := []unix.PollFd{
38+
{Fd: int32(fd), Events: unix.POLLIN | unix.POLLERR},
39+
}
40+
n, err := unix.Poll(fds, 0)
41+
if err != nil {
42+
pollErr = fmt.Errorf("poll: %w", err)
43+
}
44+
if n > 0 {
45+
// fmt.Errorf("poll: %v", fds[0].Revents)
46+
pollErr = errUnexpectedEvent
4747
}
48-
return true
4948
})
5049
if err != nil {
5150
return err
5251
}
53-
54-
return sysErr
52+
return pollErr
5553
}

Diff for: go.mod

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
module github.com/go-sql-driver/mysql
22

33
go 1.18
4+
5+
require golang.org/x/sys v0.10.0 // indirect

Diff for: go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
2+
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

Diff for: packets.go

+36-13
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,24 @@ func (mc *mysqlConn) readPacket() ([]byte, error) {
4444

4545
// check packet sync [8 bit]
4646
if data[3] != mc.sequence {
47+
var syncErr error
4748
if data[3] > mc.sequence {
48-
return nil, ErrPktSyncMul
49+
syncErr = ErrPktSyncMul
50+
} else {
51+
syncErr = ErrPktSync
4952
}
50-
return nil, ErrPktSync
53+
54+
if prevData != nil {
55+
return nil, syncErr
56+
} else {
57+
// log and ignore seqno mismatch error.
58+
// MySQL sometimes sends wrong sequence no.
59+
mc.cfg.Logger.Print(syncErr)
60+
mc.sequence = data[3] + 1
61+
}
62+
} else {
63+
mc.sequence++
5164
}
52-
mc.sequence++
5365

5466
// packets with length 0 terminate a previous packet which is a
5567
// multiple of (2^24)-1 bytes long
@@ -111,18 +123,29 @@ func (mc *mysqlConn) writePacket(data []byte) error {
111123
}
112124
var err error
113125
if mc.cfg.CheckConnLiveness {
114-
if mc.cfg.ReadTimeout != 0 {
115-
err = conn.SetReadDeadline(time.Now().Add(mc.cfg.ReadTimeout))
116-
}
117-
if err == nil {
118-
err = connCheck(conn)
126+
err = connCheck(conn)
127+
if err != nil {
128+
if err == errUnexpectedEvent {
129+
_ = conn.SetReadDeadline(time.Now().Add(time.Second))
130+
var data []byte
131+
data, err = mc.readPacket()
132+
133+
if err == nil {
134+
if data[0] == iERR {
135+
err = mc.handleErrorPacket(data)
136+
} else {
137+
err = fmt.Errorf("unexpected packet: % x", data[:128])
138+
}
139+
} else {
140+
err = fmt.Errorf("readPacket(): %w", err)
141+
}
142+
}
143+
144+
mc.cfg.Logger.Print("checkConn() failed: ", err)
145+
mc.Close()
146+
return driver.ErrBadConn
119147
}
120148
}
121-
if err != nil {
122-
mc.cfg.Logger.Print("closing bad idle connection: ", err)
123-
mc.Close()
124-
return driver.ErrBadConn
125-
}
126149
}
127150

128151
for {

0 commit comments

Comments
 (0)