Skip to content

[BUG]: Deadlock on remoteconfig when env DD_REMOTE_CONFIGURATION_ENABLED is false #3541

Open
@Dudssource

Description

@Dudssource

Tracer Version(s)

1.73.1

Go Version(s)

go version go1.24.2 darwin/arm64

Bug Report

We are getting a deadlock on the main.main goroutine when calling the method tracer.Stop(), consequently the app is hanging and not finishing properly.
Looking at the implementation, the internal/remoteconfig/remoteconfig.go#Start:191 client is being initialized before evaluating if the value of the env DD_REMOTE_CONFIGURATION_ENABLED is true|false, which causes the internal channel consumer to not be created (but the client was initialized).
Then, when the tracer.Stop method is called, it internally calls the internal/remoteconfig/remoteconfig.go#Stop:226 function, which checks if the client was initialized (which indeed was) and then sends a message to the internal stop channel (that has no consumers), leading the main goroutine to be stuck forever.
This issue occurs when instrumenting an application with serverless-init, which seems to force the value of the env to be false by default.
The suggested fix would be to move the check on line remoteconfig.go:191 before client, err := newClient(config) is invoked.

Goroutine dump

goroutine 1 gp=0xc0000061c0 m=nil [chan send]:
runtime.gopark(0x7fffb8cf4598?, 0xc000a25c78?, 0xa5?, 0x6a?, 0x7fffb8cf4568?)
	/usr/local/go/src/runtime/proc.go:424 +0xce fp=0xc000a25c48 sp=0xc000a25c28 pc=0x47162e
runtime.chansend(0xc0000b6070, 0xc000a25d18, 0x1, 0xc0000b6000?)
	/usr/local/go/src/runtime/chan.go:270 +0x38d fp=0xc000a25cb8 sp=0xc000a25c48 pc=0x40916d
runtime.chansend1(0x129d0df?, 0x2c?)
	/usr/local/go/src/runtime/chan.go:156 +0x17 fp=0xc000a25ce8 sp=0xc000a25cb8 pc=0x408dd7
gopkg.in/DataDog/dd-trace-go.v1/internal/remoteconfig.Stop.func1()
	/root/go/pkg/mod/gopkg.in/!data!dog/dd-trace-go.v1@v1.73.1/internal/remoteconfig/remoteconfig.go:226 +0x45 fp=0xc000a25d58 sp=0xc000a25ce8 pc=0xa354c5
sync.(*Once).doSlow(0x1d404a0?, 0xc000a25db0?)
	/usr/local/go/src/sync/once.go:76 +0xb4 fp=0xc000a25db8 sp=0xc000a25d58 pc=0x486cf4
sync.(*Once).Do(...)
	/usr/local/go/src/sync/once.go:67
gopkg.in/DataDog/dd-trace-go.v1/internal/remoteconfig.Stop()
	/root/go/pkg/mod/gopkg.in/!data!dog/dd-trace-go.v1@v1.73.1/internal/remoteconfig/remoteconfig.go:224 +0x37 fp=0xc000a25dd8 sp=0xc000a25db8 pc=0xa313f7
gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer.(*tracer).Stop(0xc0001be270)
	/root/go/pkg/mod/gopkg.in/!data!dog/dd-trace-go.v1@v1.73.1/ddtrace/tracer/tracer.go:767 +0xf7 fp=0xc000a25e10 sp=0xc000a25dd8 pc=0xd78f17
gopkg.in/DataDog/dd-trace-go.v1/ddtrace/internal.SetGlobalTracer({0x146f1b8, 0x1d3f8a0})
	/root/go/pkg/mod/gopkg.in/!data!dog/dd-trace-go.v1@v1.73.1/ddtrace/internal/globaltracer.go:30 +0x8f fp=0xc000a25e40 sp=0xc000a25e10 pc=0x8c4e8f
gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer.Stop()
	/root/go/pkg/mod/gopkg.in/!data!dog/dd-trace-go.v1@v1.73.1/ddtrace/tracer/tracer.go:246 +0x25 fp=0xc000a25e60 sp=0xc000a25e40 pc=0xd755a5
main.main.func1()
	/go/src/REDACTED/main.go:23 +0x18 fp=0xc000a25e70 sp=0xc000a25e60 pc=0xfa75b8
main.main()
	/go/src/REDACTED/main.go:45 +0x22d fp=0xc000a25f50 sp=0xc000a25e70 pc=0xfa756d
runtime.main()
	/usr/local/go/src/runtime/proc.go:272 +0x28b fp=0xc000a25fe0 sp=0xc000a25f50 pc=0x43d4eb
runtime.goexit({})
	/usr/local/go/src/runtime/asm_amd64.s:1700 +0x1 fp=0xc000a25fe8 sp=0xc000a25fe0 pc=0x4798a1

Code evidences

Stop() sending to the stop channel:

Image

Client initialization skipping the consumer initialization:

Image

Reproduction Code

package main

import (
	"context"
	ddtracer "gopkg.in/DataDog/dd-trace-go.v1/ddtrace/tracer"
        "os"
)

func main() {

        os.Setenv("DD_REMOTE_CONFIGURATION_ENABLED","false")

	// default context
	ctx, cancel := context.WithCancel(context.Background())

	// tracer
	ddtracer.Start(ddtracer.WithRuntimeMetrics())

	defer func() {
		cancel()
		ddtracer.Stop()
	}()

         // do something with ctx
         // myAwesomeFn(ctx)

        // main goroutine leaks after the deferred function is invoked, 
        // if we set manually the env `DD_REMOTE_CONFIGURATION_ENABLED=true`, the routine finishes as expected
}

Error Logs

No response

Go Env Output

No response

Metadata

Metadata

Assignees

Labels

bugunintended behavior that has to be fixed

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions