uber-go / dig

A reflection based dependency injection toolkit for Go.
https://go.uber.org/dig
MIT License
3.88k stars 206 forks source link

Fatal error: concurrent map read and map write #414

Open albulescu opened 3 months ago

albulescu commented 3 months ago

Describe the bug fatal error: concurrent map read and map write

goroutine 115 [running]: go.uber.org/dig.(constructorNode).CopyOrder(0x140002e3200, 0x14000168dc0, 0x14000800500) /Users/cosmin/go/pkg/mod/go.uber.org/dig@v1.17.1/constructor.go:134 +0x40 go.uber.org/dig.(Scope).Scope(0x14000168dc0, {0x102fc3dfb, 0x7}, {0x0, 0x0, 0x0}) /Users/cosmin/go/pkg/mod/go.uber.org/dig@v1.17.1/scope.go:127 +0x2b8 go.uber.org/dig.(*Container).Scope(0x140000807f8, {0x102fc3dfb, 0x7}, {0x0, 0x0, 0x0}) /Users/cosmin/go/pkg/mod/go.uber.org/dig@v1.17.1/container.go:259 +0x5c

To Reproduce

scope := di.Container().Scope("request")

        if err := scope.Provide(func() Context { return &EchoContext{c} }); err != nil {
            return err
        }

        if err := scope.Invoke(handler); err != nil {
            return err
        }

Expected behavior A clear and concise description of what you expected to happen.

Additional context

// CopyOrder copies the order for the given parent scope to the given child scope.
func (n *constructorNode) CopyOrder(parent, child *Scope) {
    n.orders[child] = n.orders[parent]
}
sywhang commented 3 months ago

Hi there, thanks for reporting this issue.

It seems like you are accessing the container object in a concurrent manner.

Exposed methods on Container are not thread safe and should not be invoked from multiple goroutines. Out of curiosity, may I ask what you are using Dig for?

albulescu commented 3 months ago

A router like .Get("/info", function(c Context, chat *Chat) {}

sywhang commented 2 months ago

Container is not thread safe and is expected to be called from a single-thread. In general I recommend against using Dig directly in user-facing code (like router).

Also see from our README:

Good for:
Powering an application framework, e.g. [Fx](https://github.com/uber-go/fx).
Resolving the object graph during process startup.
Bad for:
Using in place of an application framework, e.g. [Fx](https://github.com/uber-go/fx).
Resolving dependencies after the process has already started.
Exposing to user-land code as a [Service Locator](https://martinfowler.com/articles/injection.html#UsingAServiceLocator).