mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-09-23 01:27:04 +00:00
XHTTP client: Fix a data race in WaitReadCloser (#6694)
https://github.com/XTLS/Xray-core/pull/6694#issuecomment-5575759500 --------- Co-authored-by: 风扇滑翔翼 <Fangliding.fshxy@outlook.com>
This commit is contained in:
@@ -68,7 +68,7 @@ func (c *DefaultDialerClient) OpenStream(ctx context.Context, url string, sessio
|
|||||||
}
|
}
|
||||||
c.transportConfig.FillStreamRequest(req, sessionId, "")
|
c.transportConfig.FillStreamRequest(req, sessionId, "")
|
||||||
|
|
||||||
wrc = &WaitReadCloser{Wait: make(chan struct{})}
|
wrc = &WaitReadCloser{wait: done.New()}
|
||||||
go func() {
|
go func() {
|
||||||
resp, err := c.client.Do(req)
|
resp, err := c.client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -188,38 +188,35 @@ func (c *DefaultDialerClient) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type WaitReadCloser struct {
|
type WaitReadCloser struct {
|
||||||
Wait chan struct{}
|
wait *done.Instance
|
||||||
io.ReadCloser
|
reader atomic.Pointer[io.ReadCloser]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *WaitReadCloser) Set(rc io.ReadCloser) {
|
func (w *WaitReadCloser) Set(rc io.ReadCloser) {
|
||||||
w.ReadCloser = rc
|
w.reader.Store(&rc)
|
||||||
defer func() {
|
if w.wait.Done() {
|
||||||
if recover() != nil {
|
if p := w.reader.Swap(nil); p != nil {
|
||||||
rc.Close()
|
(*p).Close()
|
||||||
}
|
}
|
||||||
}()
|
}
|
||||||
close(w.Wait)
|
w.wait.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *WaitReadCloser) Read(b []byte) (int, error) {
|
func (w *WaitReadCloser) Read(b []byte) (int, error) {
|
||||||
if w.ReadCloser == nil {
|
rc := w.reader.Load()
|
||||||
if <-w.Wait; w.ReadCloser == nil {
|
if rc == nil {
|
||||||
|
<-w.wait.Wait()
|
||||||
|
if rc = w.reader.Load(); rc == nil {
|
||||||
return 0, io.ErrClosedPipe
|
return 0, io.ErrClosedPipe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return w.ReadCloser.Read(b)
|
return (*rc).Read(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *WaitReadCloser) Close() error {
|
func (w *WaitReadCloser) Close() error {
|
||||||
if w.ReadCloser != nil {
|
w.wait.Close()
|
||||||
return w.ReadCloser.Close()
|
if p := w.reader.Swap(nil); p != nil {
|
||||||
|
return (*p).Close()
|
||||||
}
|
}
|
||||||
defer func() {
|
|
||||||
if recover() != nil && w.ReadCloser != nil {
|
|
||||||
w.ReadCloser.Close()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
close(w.Wait)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user