Skip to content

deadlock on unexpected call with mocked argument implementing fmt.Stringer #116

@jpicht

Description

@jpicht

Actual behavior Deadlock on unexpected call to function where one or more arguments are a generated mock that implements fmt.Stringer.

Expected behavior No deadlock on an unexpected call

To Reproduce Steps to reproduce the behavior

  1. put the files below into a directory
  2. mockgen -package=deadlock -source=interfaces.go -destination=mocks.go
  3. go test -v .

interfaces.go

package deadlock

import "fmt"

type Outer interface {
	Consume(Inner)
}

type Inner interface {
	fmt.Stringer
}

deadlock_test.go

package deadlock

import (
	"testing"

	"go.uber.org/mock/gomock"
)

func TestDeadlock(t *testing.T) {
	ctrl := gomock.NewController(t)
	inner := NewMockInner(ctrl)
	outer := NewMockOuter(ctrl)
	outer.Consume(inner)
}

Additional Information

  • gomock mode (reflect or source): source
  • gomock version or git ref: v0.3.0
  • golang version: go version go1.21.3 linux/amd64

Triage Notes for the Maintainers

  1. The call to ctrl.T.Fatalf in controller.go:209 is holding ctrl.mu
  2. Fatalf will call the String() method on the mock (also unexpectedly)
  3. this will reach controller.go:200 and deadlock

backtrace

goroutine 18 [sync.Mutex.Lock]:
sync.runtime_SemacquireMutex(0x0?, 0x65?, 0x4be6c0?)
        /usr/local/go/src/runtime/sema.go:77 +0x25
sync.(*Mutex).lockSlow(0xc000196400)
        /usr/local/go/src/sync/mutex.go:171 +0x15d
sync.(*Mutex).Lock(...)
        /usr/local/go/src/sync/mutex.go:90
go.uber.org/mock/gomock.(*Controller).Call.func1(0xc0001963f0, {0x517220?, 0xc000184200}, {0x536f30, 0x6}, {0x0, 0x0, 0x0})
        .../go/pkg/mod/go.uber.org/mock@v0.3.0/gomock/controller.go:200 +0xd1                    
go.uber.org/mock/gomock.(*Controller).Call(0xc0001963f0, {0x517220, 0xc000184200}, {0x536f30, 0x6}, {0x0, 0x0, 0x0})
        .../go/pkg/mod/go.uber.org/mock@v0.3.0/gomock/controller.go:225 +0xa7                    
.../deadlock.(*MockInner).String(0xc000184200)                        
        /home/.../deadlock/mocks.go:78 +0x53                                  
fmt.(*pp).handleMethods(0xc00019a680, 0x184220?)
        /usr/local/go/src/fmt/print.go:673 +0x2b2
fmt.(*pp).printValue(0xc00019a680, {0x513ea0?, 0xc000184220?, 0x49e866?}, 0x76, 0x1)
        /usr/local/go/src/fmt/print.go:770 +0xca
fmt.(*pp).printValue(0xc00019a680, {0x50dd20?, 0xc0001a8090?, 0x5398db?}, 0x76, 0x0)
        /usr/local/go/src/fmt/print.go:912 +0x1605
fmt.(*pp).printArg(0xc00019a680, {0x50dd20?, 0xc0001a8090}, 0x76)
        /usr/local/go/src/fmt/print.go:759 +0x6a5
fmt.(*pp).doPrintf(0xc00019a680, {0x540a4e, 0x2e}, {0xc000180140?, 0x5, 0x5})
        /usr/local/go/src/fmt/print.go:1077 +0x39e
fmt.Sprintf({0x540a4e, 0x2e}, {0xc000180140, 0x5, 0x5})
        /usr/local/go/src/fmt/print.go:239 +0x53
testing.(*common).Fatalf(0xc00019e680, {0x540a4e?, 0x40ac65?}, {0xc000180140?, 0x50efa0?, 0x61ef01?})
        /usr/local/go/src/testing/testing.go:1082 +0x3f
go.uber.org/mock/gomock.(*Controller).Call.func1(0xc0001963f0, {0x5172a0?, 0xc000184210}, {0x537171, 0x7}, {0xc000184220, 0x1, 0x1})
        .../go/pkg/mod/go.uber.org/mock@v0.3.0/gomock/controller.go:209 +0x356                    
go.uber.org/mock/gomock.(*Controller).Call(0xc0001963f0, {0x5172a0, 0xc000184210}, {0x537171, 0x7}, {0xc000184220, 0x1, 0x1})
        .../go/pkg/mod/go.uber.org/mock@v0.3.0/gomock/controller.go:225 +0xa7                    
.../deadlock.(*MockOuter).Consume(0xc000184210, {0x5670e0?, 0xc000184200})                        
        /home/.../deadlock/mocks.go:43 +0xab                                  
.../deadlock.TestDeadlock(0x0?)                        
        /home/.../deadlock_test.go:13 +0x129                                           
testing.tRunner(0xc00019e680, 0x542e38)
        /usr/local/go/src/testing/testing.go:1595 +0xff
created by testing.(*T).Run in goroutine 1
        /usr/local/go/src/testing/testing.go:1648 +0x3ad
FAIL    .../deadlock    1.006s
FAIL

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions