Comments (7)
I wrote a test for this. And if you add my modification(see code block above) to stream.go
you will see that there is still data in the internal buffer to be read.
I replace everything in session.go
with this temporarily, and then i ran go test -test.v -run TestRace
many times. Sometimes it passes, sometimes it fails.
Here is the code:
package smux
import (
"io"
"log"
"math/rand"
"net"
"net/http"
"testing"
)
func init() {
go func() {
log.Println(http.ListenAndServe("localhost:6060", nil))
}()
log.SetFlags(log.LstdFlags | log.Lshortfile)
ln, err := net.Listen("tcp", "127.0.0.1:19999")
if err != nil {
// handle error
panic(err)
}
go func() {
for {
conn, err := ln.Accept()
if err != nil {
// handle error
}
go handleConnection(conn)
}
}()
}
func handleConnection(conn net.Conn) {
session, _ := Server(conn, nil)
for {
if stream, err := session.AcceptStream(); err == nil {
go func(s io.ReadWriteCloser) {
buf := make([]byte, 50000)
read := 0
for read != len(buf) {
n, err := s.Read(buf[read:])
if err != nil {
log.Fatalf("server read err: %v\n", err)
}
read += n
}
s.Write(buf)
// Server closes stream properly
s.Close()
// And immedately after closes the session
// which still causes the race to happen
session.Close()
}(stream)
} else {
return
}
}
}
func TestRace(t *testing.T) {
cli, err := net.Dial("tcp", "127.0.0.1:19999")
if err != nil {
t.Fatal(err)
}
session, _ := Client(cli, nil)
stream, _ := session.OpenStream()
data := make([]byte, 50000)
for i := range data {
data[i] = byte(rand.Int())
}
if _, err = stream.Write(data); err != nil {
t.Fatalf("write to stream failed: %v\n", err)
}
buf := make([]byte, len(data))
read := 0
for read != len(buf) {
if n, err := stream.Read(buf[read:]); err == nil {
read += n
} else {
log.Fatalf("Read error: %v\n", err)
}
}
if string(buf) != string(data) {
t.Fatal("Buf and data are not eq\n")
}
}
from smux.
https://github.com/xtaci/smux/blob/master/stream.go#L55
are your referring to this ?
AFAIK,the behavior of reading after close is not specified in net.Conn.
also , it's completly ok to remove this select.
from smux.
Yes, exactly. I would expect that the internal buffer of stream would have to be completely read(via stream.Read
) by a consumer before it says that the pipe is broken. On the server session.Close()
was run after stream.Write(...)
so i would expect to receive all data from the write operation before receiving the "broken pipe" message.
With a normal net.Conn
, if you do this
buf := make([]byte, LEN)
conn.Write(buf)
conn.Close()
the client will first receive 50.000 bytes and then the connection will be closed.
But with smux it becomes a race because of the multiplexing. The client might receive some data, and then maybe a signal saying the session was closed before the rest of the data has been read/consumed.
from smux.
try the commit pls
from smux.
Works like a charm for me!
from smux.
happy to hear
from smux.
Thanks for your effort, closing! 🥇
from smux.
Related Issues (20)
- 修正一处细节, HOT 4
- Blocked streams under heavy load HOT 5
- smux multiplexes multiple TCP connections?
- Stream does not return net.Error for timeouts
- alloc module memory release HOT 1
- What's the difference between version1 and version2 in smux.Config? HOT 4
- cmdFIN and cmdPSH race condition HOT 2
- 如何检测一个 Conn 是否 muxing?
- proposal: add option to not close idle session HOT 1
- 一个stream不读数据,另一端stream一直写,直到缓冲满。这个时候绑定在conn上的Session将不能执行任何指令。 HOT 4
- 写超时,应用层选择重发 HOT 1
- 看了好多遍都没看懂,这个地方没有错误吗 HOT 15
- TestGetDieCh() strange behaviour seems cause by racing
- 建议增加一个 Session.GetCloseChan() 的函数,可以使用select快速得知连接已经被断开 HOT 6
- An extra character appears when using io.Copy
- 想问下协议版本1和2有什么区别 HOT 5
- 能否支持自动匹配客户端版本 (version 1,2) HOT 2
- Multiplexing over SCTP unordered mode HOT 2
- OpenStream似乎有并行性能问题
- 当并发newStream 较高时,recvLoop存在内存泄露 HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from smux.