mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-08-25 04:17:15 +00:00
fix(xray): guard log-writer race and bound handler gRPC deadlines (#5442)
* perf(xray): compile log/traffic regexps once at package scope GetTraffic recompiled two stats regexps on every traffic tick, and LogWriter.Write recompiled two more on every log line. Hoist all four to package-level vars so they compile once at load instead of per call on hot paths. * fix(xray): guard LogWriter.lastLine against the GetResult reader race Write is driven by the Xray process goroutine while Process.GetResult reads lastLine from the caller's goroutine, so the unsynchronized field is a data race under `go test -race`. Add an RWMutex and route every write through setLastLine; GetResult reads via LastLine(). * fix(xray): bound handler gRPC calls with a deadline AddInbound, DelInbound and the AddUser AlterInbound call used context.Background(), so a hung core connection could block the caller indefinitely (for example while the process restart lock is held). Give them a 10s deadline (handlerRPCTimeout) and a nil-client guard, matching the other handler operations.
This commit is contained in:
+23
-3
@@ -123,8 +123,16 @@ func (x *XrayAPI) Close() {
|
||||
x.isConnected = false
|
||||
}
|
||||
|
||||
// handlerRPCTimeout bounds per-call gRPC handler operations (add/remove inbound,
|
||||
// alter user) so a hung core connection cannot block the caller indefinitely —
|
||||
// for example while the process restart lock is held.
|
||||
const handlerRPCTimeout = 10 * time.Second
|
||||
|
||||
// AddInbound adds a new inbound configuration to the Xray core via gRPC.
|
||||
func (x *XrayAPI) AddInbound(inbound []byte) error {
|
||||
if x.HandlerServiceClient == nil {
|
||||
return common.NewError("xray HandlerServiceClient is not initialized")
|
||||
}
|
||||
client := *x.HandlerServiceClient
|
||||
|
||||
conf := new(conf.InboundDetourConfig)
|
||||
@@ -140,15 +148,22 @@ func (x *XrayAPI) AddInbound(inbound []byte) error {
|
||||
}
|
||||
inboundConfig := command.AddInboundRequest{Inbound: config}
|
||||
|
||||
_, err = client.AddInbound(context.Background(), &inboundConfig)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), handlerRPCTimeout)
|
||||
defer cancel()
|
||||
_, err = client.AddInbound(ctx, &inboundConfig)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// DelInbound removes an inbound configuration from the Xray core by tag.
|
||||
func (x *XrayAPI) DelInbound(tag string) error {
|
||||
if x.HandlerServiceClient == nil {
|
||||
return common.NewError("xray HandlerServiceClient is not initialized")
|
||||
}
|
||||
client := *x.HandlerServiceClient
|
||||
_, err := client.RemoveInbound(context.Background(), &command.RemoveInboundRequest{
|
||||
ctx, cancel := context.WithTimeout(context.Background(), handlerRPCTimeout)
|
||||
defer cancel()
|
||||
_, err := client.RemoveInbound(ctx, &command.RemoveInboundRequest{
|
||||
Tag: tag,
|
||||
})
|
||||
return err
|
||||
@@ -505,9 +520,14 @@ func (x *XrayAPI) AddUser(Protocol string, inboundTag string, user map[string]an
|
||||
return nil
|
||||
}
|
||||
|
||||
if x.HandlerServiceClient == nil {
|
||||
return common.NewError("xray HandlerServiceClient is not initialized")
|
||||
}
|
||||
client := *x.HandlerServiceClient
|
||||
|
||||
_, err = client.AlterInbound(context.Background(), &command.AlterInboundRequest{
|
||||
ctx, cancel := context.WithTimeout(context.Background(), handlerRPCTimeout)
|
||||
defer cancel()
|
||||
_, err = client.AlterInbound(ctx, &command.AlterInboundRequest{
|
||||
Tag: inboundTag,
|
||||
Operation: serial.ToTypedMessage(&command.AddUserOperation{
|
||||
User: &protocol.User{
|
||||
|
||||
Reference in New Issue
Block a user