man-mu commented on code in PR #3701:
URL: https://github.com/apache/dubbo-go/pull/3701#discussion_r3855048802
##########
filter/accesslog/filter.go:
##########
@@ -90,21 +99,21 @@ type Filter struct {
ctx context.Context
cancel context.CancelFunc
shutdownOnce sync.Once
+ wg sync.WaitGroup // tracks the processLogs goroutine
}
func newFilter() filter.Filter {
- if accessLogFilter == nil {
- once.Do(func() {
- ctx, cancel := context.WithCancel(context.Background())
- accessLogFilter = &Filter{
- logChan: make(chan Data, LogMaxBuffer),
- fileCache: make(map[string]*os.File),
- ctx: ctx,
- cancel: cancel,
- }
- go accessLogFilter.processLogs()
- })
- }
+ once.Do(func() {
+ ctx, cancel := context.WithCancel(context.Background())
+ accessLogFilter = &Filter{
+ logChan: make(chan Data, LogMaxBuffer),
+ fileCache: make(map[string]*os.File),
+ ctx: ctx,
+ cancel: cancel,
+ }
+ accessLogFilter.wg.Add(1)
+ go accessLogFilter.processLogs()
+ })
return accessLogFilter
}
Review Comment:
已修复(4eca148d):
方案是把初始化闭包提取为 `doInit()`,并让 `Shutdown()` 入口也调用 `once.Do(doInit)`——`sync.Once`
在此充当初始化屏障:并发调用会阻塞等待进行中的初始化完成(或由自己执行)。这样无论与首次 `newFilter()` 谁先谁后,同一次
`Shutdown()` 返回时 filter 必然已完成发布并被本次调用关闭,不会再出现早退于发布的情况。
需要说明一点:对从未使用过的进程调用 `Shutdown()` 现在会先完成一次轻量初始化再立即关闭(以前是纯
no-op),我认为用这点微小代价换取「返回即已停止」的确定性语义是值得的,若有不妥之处还请指正。
测试也按建议调整了:去掉了第二次补偿调用,`TestAccessLogFilterConcurrentInitAndShutdown`
现在直接断言竞速双方返回后 `processLogs` 必须已经退出,不再有兜底逻辑。顺带把 `FileHandleManagement` 里最后一个固定
Sleep 也换成了确定性轮询,至此整个包里没有时间依赖断言了。
`go test -race -count=30 ./filter/accesslog/` 通过
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]