Sfoglia il codice sorgente

SplitHTTP server: Fix panic during concurrent Close and Push (#3593)

When Close and Push are called concurrently, it may happen that Push attempts to write to an already-closed channel, and trigger a panic.

From a user perspective, it results in logs like this:

    http: panic serving 172.19.0.6:50476: send on closed channel

It's probably triggered when download is closed at the same time an upload packet is submitted.

These panics don't crash the server and the inbound is still usable.
mmmray 1 anno fa
parent
commit
2becdd6414
1 ha cambiato i file con 13 aggiunte e 5 eliminazioni
  1. 13 5
      transport/internet/splithttp/upload_queue.go

+ 13 - 5
transport/internet/splithttp/upload_queue.go

@@ -6,6 +6,7 @@ package splithttp
 import (
 	"container/heap"
 	"io"
+	"sync"
 
 	"github.com/xtls/xray-core/common/errors"
 )
@@ -16,11 +17,12 @@ type Packet struct {
 }
 
 type uploadQueue struct {
-	pushedPackets chan Packet
-	heap          uploadHeap
-	nextSeq       uint64
-	closed        bool
-	maxPackets    int
+	pushedPackets   chan Packet
+	writeCloseMutex sync.Mutex
+	heap            uploadHeap
+	nextSeq         uint64
+	closed          bool
+	maxPackets      int
 }
 
 func NewUploadQueue(maxPackets int) *uploadQueue {
@@ -34,6 +36,9 @@ func NewUploadQueue(maxPackets int) *uploadQueue {
 }
 
 func (h *uploadQueue) Push(p Packet) error {
+	h.writeCloseMutex.Lock()
+	defer h.writeCloseMutex.Unlock()
+
 	if h.closed {
 		return errors.New("splithttp packet queue closed")
 	}
@@ -43,6 +48,9 @@ func (h *uploadQueue) Push(p Packet) error {
 }
 
 func (h *uploadQueue) Close() error {
+	h.writeCloseMutex.Lock()
+	defer h.writeCloseMutex.Unlock()
+
 	h.closed = true
 	close(h.pushedPackets)
 	return nil