Goroutine在EKS Pod中引发Segmentation Fault的原因排查问询
问题场景
在EKS Pod环境中,通过Goroutine调用GetRCDetails函数时,以下代码行触发Segmentation Fault:
l.Mongo.Client.Collection(RCDataCollection).FindOne(ctx.Ctx, filter).Decode(&rcResponse.Data)
非Goroutine环境下直接调用该函数则运行正常。已排查确认代码中所用变量均不为nil,但仍出现如下错误:
panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x13905b6]
相关函数代码
func (l *LS) GetRCDetails(ctx *common.Context, rcRequest vm.RCRequest) (vm.RCResponseData, base.VError) { defer common.StartSegment(ctx, "GetRCDetails").End() var rcResponse vm.RCResponse filter := bson.M{"reg_no": rcRequest.RCNumber} err := l.Mongo.Client.Collection(RCDataCollection).FindOne(ctx.Ctx, filter).Decode(&rcResponse.Data) ctx.Logger.Infof("error in decode :: %v", err) //to update existing vehicle data for additional fields if err == nil && rcResponse.Data.RegNo != "" && rcResponse.Data.Engine != "" { return rcResponse.Data, nil } ctx.Logger.Infof("Calling Notification service to get RC for RegNo:%s", rcRequest.RCNumber) _, rcResponse, err = l.notificationService.GetRCResponse(ctx, rcRequest) ctx.Logger.Infof("Received RC response from Notification service for RegNo:%s", rcRequest.RCNumber) if err != nil || rcResponse.Message != "" { verror := base.NewVahakError(http.StatusBadRequest, errors.New(rcResponse.Message)).DoNotSentryInstance() return rcResponse.Data, verror } rcResponse.Data.CreatedAt = time.Now().UTC() rcResponse.Data.UpdatedAt = time.Now().UTC() l.Mongo.Save(ctx, RCDataCollection, rcResponse.Data) return rcResponse.Data, nil }
可能的原因分析
MongoDB驱动的并发安全性问题
部分旧版本的MongoDB驱动客户端实例并非完全并发安全,当多个Goroutine共享同一个l.Mongo.Client实例时,内部未同步的状态可能引发竞态条件,导致内存访问错误。即使确认l.Mongo.Client不为nil,并发场景下驱动内部的状态损坏仍可能触发空指针解引用。建议检查驱动版本,尝试升级到最新稳定版。自定义Context的并发安全问题
代码中使用的*common.Context如果内部包含非线程安全的字段(比如未加锁的日志实例、共享状态变量),在Goroutine中并发访问时可能导致内存结构损坏,间接引发后续MongoDB操作的空指针异常。需要确认该自定义Context的实现是否满足并发安全要求。EKS容器环境的资源限制问题
EKS Pod的内存限制过低时,高并发场景下可能触发内存分配异常,甚至在OOM前出现非法内存访问;或者MongoDB服务端在高并发压力下返回异常响应,驱动处理时出现未预期的空指针。可以检查Pod的资源配置,适当调整内存限额,同时监控MongoDB服务端的响应状态。驱动内部的竞态条件bug
即使驱动文档声明并发安全,也可能存在特定场景下的隐藏bug,比如FindOne与Decode操作并发执行时,内部缓冲区或状态变量未正确同步,导致空指针解引用。升级驱动到最新版本通常能修复这类已知问题。变量内存分配问题
Goroutine中的变量可能被分配到栈上,当栈扩容或变量被意外回收时,可能导致指针指向无效内存。可以尝试将rcResponse改为堆分配(比如用rcResponse := new(vm.RCResponse)代替var rcResponse vm.RCResponse),验证是否能缓解问题。
内容的提问来源于stack exchange,提问作者Abhay Kumar

