Fix data loss on TCP reconnect:
1. Fixed ByteFIFO (fifo.go): Changed Dequeue(), DequeueOrWait(), and DequeueOrWaitContext() to always copy() data into a new byte slice instead of just slicing the buffer. 2. Fixed TCP server logic (tcpserver.go): Changed the send goroutine to poll for data availability (without dequeueing) using GetLen(), then sleep briefly to batch incoming data, and finally dequeue all available data at once. This avoids the race condition where we were splitting dequeue operations and losing bytes in between.
This commit is contained in:
27
fifo.go
27
fifo.go
@@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
)
|
||||
|
||||
@@ -50,7 +51,8 @@ func (f *ByteFIFO) Dequeue(n int) ([]byte, error) {
|
||||
n = len(f.buffer)
|
||||
}
|
||||
|
||||
data := f.buffer[:n]
|
||||
data := make([]byte, n)
|
||||
copy(data, f.buffer[:n])
|
||||
f.buffer = f.buffer[n:]
|
||||
return data, nil
|
||||
}
|
||||
@@ -65,7 +67,8 @@ func (f *ByteFIFO) DequeueOrWait(n int) ([]byte, error) {
|
||||
f.cond.Wait()
|
||||
}
|
||||
|
||||
data := f.buffer[:n]
|
||||
data := make([]byte, n)
|
||||
copy(data, f.buffer[:n])
|
||||
f.buffer = f.buffer[n:]
|
||||
return data, nil
|
||||
}
|
||||
@@ -92,8 +95,18 @@ func (f *ByteFIFO) DequeueOrWaitContext(ctx context.Context, n int) ([]byte, err
|
||||
}
|
||||
}
|
||||
|
||||
data = f.buffer[:n]
|
||||
// Debug: print first 16 bytes of buffer before dequeueing
|
||||
debugLen := len(f.buffer)
|
||||
if debugLen > 16 {
|
||||
debugLen = 16
|
||||
}
|
||||
writeDebug(fmt.Sprintf("DequeueOrWaitContext: buffer has %d bytes, first %d bytes: %x, dequeueing %d bytes", len(f.buffer), debugLen, f.buffer[:debugLen], n), 1)
|
||||
|
||||
data = make([]byte, n)
|
||||
copy(data, f.buffer[:n])
|
||||
f.buffer = f.buffer[n:]
|
||||
|
||||
writeDebug(fmt.Sprintf("DequeueOrWaitContext: dequeued data: %x, buffer now has %d bytes", data, len(f.buffer)), 1)
|
||||
}()
|
||||
|
||||
select {
|
||||
@@ -129,6 +142,14 @@ func (f *ByteFIFO) Capacity() int {
|
||||
return f.cap
|
||||
}
|
||||
|
||||
// Clear removes all data from the buffer.
|
||||
func (f *ByteFIFO) Clear() {
|
||||
f.mutex.Lock()
|
||||
defer f.mutex.Unlock()
|
||||
|
||||
f.buffer = make([]byte, 0, f.cap)
|
||||
}
|
||||
|
||||
// *****
|
||||
|
||||
type StringFIFO struct {
|
||||
|
||||
Reference in New Issue
Block a user