Skip to content

Commit

Permalink
timeout on singleton deadlock, closes #10
Browse files Browse the repository at this point in the history
  • Loading branch information
bastianccm committed Aug 24, 2020
1 parent 76908a0 commit 7f340be
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 0 deletions.
19 changes: 19 additions & 0 deletions scope.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package dingo

import (
"fmt"
"reflect"
"sync"
"time"
)

type (
Expand Down Expand Up @@ -56,7 +58,24 @@ func (s *SingletonScope) ResolveType(t reflect.Type, annotation string, unscoped
if l, ok := s.instanceLock[ident]; ok {
// we have the instance lock
s.mu.Unlock()

ticker := time.NewTimer(10 * time.Second)
go func() {
<-ticker.C
path := t.PkgPath()
if path == "" {
if t.Kind() == reflect.Ptr {
path = t.Elem().PkgPath()
}
}
if path != "" {
path += "."
}
path += t.Name()
panic(fmt.Sprintf("Singleton: timed out waiting for instance lock: type: %q, annotation: %q", path, annotation))
}()
l.RLock()
ticker.Stop()
defer l.RUnlock()

instance, _ := s.instances.Load(ident)
Expand Down
20 changes: 20 additions & 0 deletions scope_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,3 +148,23 @@ func TestInheritedScope(t *testing.T) {
secondI := i.(*inheritedScopeInjected)
assert.Same(t, firstI.i, secondI.i)
}

type circSingletonA struct {
B *circSingletonB `inject:""`
}
type circSingletonB struct {
A *circSingletonA `inject:""`
}

func TestCircularSingletonBinding(t *testing.T) {
EnableCircularTracing()
defer func() {
traceCircular = nil
}()
injector, err := NewInjector()
assert.NoError(t, err)
injector.Bind(new(circSingletonA)).In(Singleton)
assert.Panics(t, func() {
injector.GetInstance(new(circSingletonA))
})
}

0 comments on commit 7f340be

Please sign in to comment.