Detailed steps to reproduce the problem?
The program below will demonstrate the leak by incrementally outputting goroutine counts. It also exposes a pprof server at localhost:8080 for profile analysis.
package main import ( "context" "fmt" "log" "net/http" _ "net/http/pprof" "runtime" "time" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) func main() { go func() { log.Println(http.ListenAndServe("localhost:8080", nil)) }() ctx := context.Background() uri := "mongodb://localhost:27017" opts := options.Client().ApplyURI(uri).SetCompressors([]string{"zstd"}) client, err := mongo.Connect(ctx, opts) if err != nil { log.Fatalf("Error connecting to mongo server: %v", err) } defer func() { if err = client.Disconnect(ctx); err != nil { panic(err) } }() connectCtx, cancel := context.WithTimeout(ctx, time.Second*5) defer cancel() if err := client.Ping(connectCtx, nil); err != nil { log.Fatalf("Error pinging mongo server: %v\n", err) } type TestStruct struct { X string `bson:"x"` } collection := client.Database("leaktest").Collection("testcollection") if _, err := collection.InsertOne(ctx, TestStruct{X: "123"}); err != nil { log.Fatalf("Error intializing collection: %v\n", err) } for i := 0; i < 30; i++ { var doc TestStruct if err := collection.FindOne(ctx, bson.M{"x": "123"}).Decode(&doc); err != nil { log.Fatalf("Error fetching document: %v\n", err) } time.Sleep(1 * time.Second) runtime.GC() fmt.Printf("Goroutines: %d\n", runtime.NumGoroutine()) } }
Sample output from pprof while running:
go tool pprof -top http://localhost:8080/debug/pprof/goroutine File: main Type: goroutine Time: Sep 12, 2024 at 1:39pm (PDT) Showing nodes accounting for 388, 100% of 388 total flat flat% sum% cum cum% 387 99.74% 99.74% 387 99.74% runtime.gopark 1 0.26% 100% 1 0.26% runtime.goroutineProfileWithLabels 0 0% 100% 378 97.42% github.com/klauspost/compress/zstd.(*blockDec).startDecoder 0 0% 100% 1 0.26% go.mongodb.org/mongo-driver/x/mongo/driver.Operation.ExecuteExhaust 0 0% 100% 1 0.26% go.mongodb.org/mongo-driver/x/mongo/driver.Operation.readWireMessage 0 0% 100% 1 0.26% go.mongodb.org/mongo-driver/x/mongo/driver/operation.(*Hello).StreamResponse 0 0% 100% 1 0.26% go.mongodb.org/mongo-driver/x/mongo/driver/topology.(*Server).check 0 0% 100% 1 0.26% go.mongodb.org/mongo-driver/x/mongo/driver/topology.(*Server).update 0 0% 100% 1 0.26% go.mongodb.org/mongo-driver/x/mongo/driver/topology.(*cancellListener).Listen 0 0% 100% 1 0.26% go.mongodb.org/mongo-driver/x/mongo/driver/topology.(*connection).read 0 0% 100% 1 0.26% go.mongodb.org/mongo-driver/x/mongo/driver/topology.(*connection).readWireMessage 0 0% 100% 2 0.52% go.mongodb.org/mongo-driver/x/mongo/driver/topology.(*pool).createConnections 0 0% 100% 2 0.52% go.mongodb.org/mongo-driver/x/mongo/driver/topology.(*pool).createConnections.func2
Definition of done: what must be done to consider the task complete?
Enabling zstd compression on the client no longer leaks goroutines.
The exact Go version used, with patch level:
$ go version
go version go1.22.7 darwin/arm64
The exact version of the Go driver used:
$ go list -m go.mongodb.org/mongo-driver
go.mongodb.org/mongo-driver v1.16.1
Describe how MongoDB is set up. Local vs Hosted, version, topology, load balanced, etc.
For the reproduction using the program above a local MongoDB docker container was running, using the mongo:7.0 image.
Security Vulnerabilities
If you’ve identified a security vulnerability in a driver or any other MongoDB project, please report it according to the instructions here
- is duplicated by
-
GODRIVER-3360 Bump github.com/klauspost/compress from 1.13.6 to 1.17.10
- Closed