I am not sure if this is a problem or a feature, but invoking dependencies after shutdown creates a race condition (runnable code at https://goplay.tools/snippet/vIQ3Pwu4lw1):
package main
import (
"log"
"sync"
"time"
"github.com/samber/do"
)
type Service struct{}
func main() {
var wg sync.WaitGroup
i := do.New()
do.Provide(i, func(injector *do.Injector) (*Service, error) {
return &Service{}, nil
})
// uncommenting the line below gives an error: `Invoking after shutdown error: DI: could not find service `*main.Service`, available services:`
//_ = do.MustInvoke[*Service](i)
wg.Add(1)
go func() {
defer wg.Done()
time.Sleep(time.Second * 1)
_, err := do.Invoke[*Service](i)
if err != nil {
log.Printf("Invoking after shutdown error: %v\n", err)
return
}
}()
err := i.Shutdown()
if err != nil {
log.Printf("Shutdown error: %v\n", err)
}
wg.Wait()
log.Println("Finished")
}
When running with go run -race . it detects a race condition:
==================
WARNING: DATA RACE
Write at 0x00c0000b60c8 by goroutine 6:
github.com/samber/do.(*Injector).onServiceInvoke()
/Users/ivand/go/pkg/mod/github.com/samber/do@v1.6.0/injector.go:278 +0x120
github.com/samber/do.InvokeNamed[...]()
/Users/ivand/go/pkg/mod/github.com/samber/do@v1.6.0/di.go:128 +0xc8
github.com/samber/do.Invoke[...]()
/Users/ivand/go/pkg/mod/github.com/samber/do@v1.6.0/di.go:101 +0x6c
main.main.func2()
/Users/ivand/IdeaProjects/untitled1/main.go:32 +0x7c
Previous read at 0x00c0000b60c8 by main goroutine:
github.com/samber/do.(*Injector).Shutdown()
/Users/ivand/go/pkg/mod/github.com/samber/do@v1.6.0/injector.go:124 +0x1b0
main.main()
/Users/ivand/IdeaProjects/untitled1/main.go:39 +0x130
Goroutine 6 (running) created at:
main.main()
/Users/ivand/IdeaProjects/untitled1/main.go:27 +0x128
==================
2023/04/28 12:55:27 Finished
Found 1 data race(s)
exit status 66
Is this the intended way it supposed to work? Is the shutdown procedure expected to be a final call with no invoking of services after it?
I haven't dug deeply in the source code, but apparently the shutdown procedure does not operate under the write lock. Is there a particular reason for that?
I am not sure if this is a problem or a feature, but invoking dependencies after shutdown creates a race condition (runnable code at https://goplay.tools/snippet/vIQ3Pwu4lw1):
When running with
go run -race .
it detects a race condition:Is this the intended way it supposed to work? Is the shutdown procedure expected to be a final call with no invoking of services after it?
I haven't dug deeply in the source code, but apparently the shutdown procedure does not operate under the write lock. Is there a particular reason for that?