Skip to content

Commit 19171b5

Browse files
authored
Close connection on ErrPktSync and ErrPktSyncMul (#1473)
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 22e750b commit 19171b5

File tree

3 files changed

+30
-24
lines changed

3 files changed

+30
-24
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ Maciej Zimnoch <maciej.zimnoch at codilime.com>
7777
Michael Woolnough <michael.woolnough at gmail.com>
7878
Nathanial Murphy <nathanial.murphy at gmail.com>
7979
Nicola Peduzzi <thenikso at gmail.com>
80+
Oliver Bone <owbone at github.com>
8081
Olivier Mengué <dolmen at cpan.org>
8182
oscarzhao <oscarzhaosl at gmail.com>
8283
Paul Bonser <misterpib at gmail.com>

packets.go

Lines changed: 1 addition & 0 deletions
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

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -133,30 +133,34 @@ func TestReadPacketSingleByte(t *testing.T) {
133133
}
134134

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

0 commit comments

Comments
 (0)