Skip to content

Commit 88bbc4b

Browse files
committed
Close connection on ErrPktSync and ErrPktSyncMul
An `ErrPktSync` or `ErrPktSyncMul` error always means that a packet header has been read, but since the sequence ID was not correct then the packet payload has not been read. This results in the connection being left in a broken state, since any future operations will always result in a "busy buffer" error. Keeping such connections alive leads to them being repeatedly returned to the pool in this state, which can in turn result in a large number of failures due to these "busy buffer" errors. This commit fixes this problem by simply closing the connection before returning either `ErrPktSync` or `ErrPktSyncMul`. This ensures that the connection won't be returned to the pool, preventing it from causing any further errors.
1 parent f20b286 commit 88bbc4b

File tree

3 files changed

+30
-24
lines changed

3 files changed

+30
-24
lines changed

AUTHORS

+1
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ Maciej Zimnoch <maciej.zimnoch at codilime.com>
7474
Michael Woolnough <michael.woolnough at gmail.com>
7575
Nathanial Murphy <nathanial.murphy at gmail.com>
7676
Nicola Peduzzi <thenikso at gmail.com>
77+
Oliver Bone <owbone at github.com>
7778
Olivier Mengué <dolmen at cpan.org>
7879
oscarzhao <oscarzhaosl at gmail.com>
7980
Paul Bonser <misterpib at gmail.com>

packets.go

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ func (mc *mysqlConn) readPacket() ([]byte, error) {
4444

4545
// check packet sync [8 bit]
4646
if data[3] != mc.sequence {
47+
mc.Close()
4748
if data[3] > mc.sequence {
4849
return nil, ErrPktSyncMul
4950
}

packets_test.go

+28-24
Original file line numberDiff line numberDiff line change
@@ -128,30 +128,34 @@ func TestReadPacketSingleByte(t *testing.T) {
128128
}
129129

130130
func TestReadPacketWrongSequenceID(t *testing.T) {
131-
conn := new(mockConn)
132-
mc := &mysqlConn{
133-
buf: newBuffer(conn),
134-
}
135-
136-
// too low sequence id
137-
conn.data = []byte{0x01, 0x00, 0x00, 0x00, 0xff}
138-
conn.maxReads = 1
139-
mc.sequence = 1
140-
_, err := mc.readPacket()
141-
if err != ErrPktSync {
142-
t.Errorf("expected ErrPktSync, got %v", err)
143-
}
144-
145-
// reset
146-
conn.reads = 0
147-
mc.sequence = 0
148-
mc.buf = newBuffer(conn)
149-
150-
// too high sequence id
151-
conn.data = []byte{0x01, 0x00, 0x00, 0x42, 0xff}
152-
_, err = mc.readPacket()
153-
if err != ErrPktSyncMul {
154-
t.Errorf("expected ErrPktSyncMul, got %v", err)
131+
for _, testCase := range []struct {
132+
ClientSequenceID byte
133+
ServerSequenceID byte
134+
ExpectedErr error
135+
}{
136+
{
137+
ClientSequenceID: 1,
138+
ServerSequenceID: 0,
139+
ExpectedErr: ErrPktSync,
140+
},
141+
{
142+
ClientSequenceID: 0,
143+
ServerSequenceID: 0x42,
144+
ExpectedErr: ErrPktSyncMul,
145+
},
146+
} {
147+
conn, mc := newRWMockConn(testCase.ClientSequenceID)
148+
149+
conn.data = []byte{0x01, 0x00, 0x00, testCase.ServerSequenceID, 0xff}
150+
_, err := mc.readPacket()
151+
if err != testCase.ExpectedErr {
152+
t.Errorf("expected %v, got %v", testCase.ExpectedErr, err)
153+
}
154+
155+
// connection should not be returned to the pool in this state
156+
if mc.IsValid() {
157+
t.Errorf("expected IsValid() to be false")
158+
}
155159
}
156160
}
157161

0 commit comments

Comments
 (0)