Browse Source

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.
pull/3600/head
mmmray 4 months ago committed by GitHub
parent
commit
2becdd6414
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 18
      transport/internet/splithttp/upload_queue.go

18
transport/internet/splithttp/upload_queue.go

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

Loading…
Cancel
Save