Skip to content

Conversation

patterniha
Copy link
Collaborator

@patterniha patterniha commented Jul 6, 2025

func (m *ClientWorker) Dispatch(ctx context.Context, link *transport.Link) bool {
if m.IsFull() || m.Closed() {
return false
}
sm := m.sessionManager
s := sm.Allocate()

if this function run concurrent from two goroutine, some problems may arise, let explain why:

suppose m.strategy.MaxConcurrency is set to 4, and currently we have 3 sessions for m.sessionManager.

suppose goroutine-A and goroutine-B run this function concurrency, because we have 3 sessions and MaxCuncurrency is set to 4, m.IsFull() is false for both goroutine, so both goroutine will run sm.Allocate().

although sessionManager has it's own Lock, but it does not help in this situation, and sm.Allocate() create a new session for each goroutine.

so after running this two goroutine two new sessions created and the number of sessions reach to 5, but MaxConcurrency is set to 4, so we exceeded the value of MaxConcurrency !!!

///

so we need another sync.Mutex lock for running this dispatch, to make sure we never exceed the MaxConcurrency/MaxConnection.

also, m.IsFull() contain m.Closed(), so there is no need to check it again.

@Fangliding
Copy link
Member

Fangliding commented Jul 8, 2025

这样可以省掉一把锁的样子 不会损失任何性能

@patterniha
Copy link
Collaborator Author

patterniha commented Jul 8, 2025

@Fangliding

we should also care about MaxConnection, so add it too.

@Fangliding
Copy link
Member

都是3没有问题 allocate是原子的

@patterniha
Copy link
Collaborator Author

patterniha commented Jul 8, 2025

@Fangliding

you should pass m.Strategy by reference -> *m.Strategy.

otherwise it is possible both goroutine use 3.

@Fangliding
Copy link
Member

没看懂你在表达啥 use 33 是什么

@Fangliding
Copy link
Member

Fangliding commented Jul 8, 2025

那就让它copy不就好了 反正这个值又不会变 是个常量 只会读而已

@patterniha
Copy link
Collaborator Author

patterniha commented Jul 8, 2025

you are right, i just confused for a moment.

anyway, there is no need to revert my last fix.

Fangliding
Fangliding previously approved these changes Jul 8, 2025
@patterniha patterniha mentioned this pull request Jul 8, 2025
@patterniha
Copy link
Collaborator Author

patterniha commented Jul 8, 2025

i change server.go base on our discussion in #4876.

I only added the minimum changes required, please check, thx.

@patterniha patterniha changed the title MUX: ClientWorker-Dispatch needs goroutine-Lock to make sure we never exceed the MaxConcurrency. MUX: Refine and fix some occasional problems Jul 8, 2025
@patterniha patterniha changed the title MUX: Refine and fix some occasional problems MUX: Refine and Fix some occasional problems Jul 8, 2025
@patterniha patterniha force-pushed the fix-mux branch 2 times, most recently from eb2b5bc to efe8179 Compare July 8, 2025 23:33
@Fangliding Fangliding marked this pull request as draft July 9, 2025 06:35
@patterniha patterniha requested a review from Fangliding July 9, 2025 15:43
@patterniha
Copy link
Collaborator Author

Screenshot 2025-07-09 193732

@Fangliding

I tested, if we don't close writer explicitly, it takes a few seconds to close the connection.
this is because of policy settings.

but all sessions is closed and there is no data to send, so it is useless to wait before closing the connection.

also, if ctx.Done is happen, the connection is remain open.

///

also, returning s.Close(false) instead of buf.Copy(rr, buf.Discard) in line 238, is definitely the author's mistake.

@RPRX RPRX merged commit 308f8a7 into XTLS:main Jul 23, 2025
39 checks passed
@patterniha patterniha deleted the fix-mux branch July 23, 2025 15:28
maoxikun added a commit to maoxikun/Xray-core that referenced this pull request Aug 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants