Skip to content

blocked in BorrowObject #44

@chensheng0

Description

@chensheng0

Seeing

blocked in BorrowObject

Environment

GO VERSION: 1.13
ARCH="amd64"
HOST="darwin"

Code

package main

import (
	"context"
	"fmt"
	"strconv"
	"sync/atomic"
	"time"

	pool "github.com/jolestar/go-commons-pool"
)

func main() {
	type myPoolObject struct {
		s string
	}

	v := uint64(0)
	factory := pool.NewPooledObjectFactorySimple(
		func(context.Context) (interface{}, error) {
			return &myPoolObject{
					s: strconv.FormatUint(atomic.AddUint64(&v, 1), 10),
				},
				nil
		})

	ctx := context.Background()
	pc := pool.NewDefaultPoolConfig()
	pc.MinIdle = 1
	pc.MaxIdle = 1
	pc.MaxTotal = 1
	pc.MinEvictableIdleTime = time.Duration(1) * time.Minute
	p := pool.NewObjectPool(context.Background(), factory, pc)

	// to avoid this error: all goroutines are asleep - deadlock!
	go func() {
		for {
			i := 100
			i = i + 1
		}
	}()

	for {
		obj, err := p.BorrowObject(ctx)
		if err != nil {
			panic(err)
		}
		go func(obj interface{}) {
			o := obj.(*myPoolObject)
			fmt.Println(time.Now(), " result: ", o.s)
			err = p.ReturnObject(ctx, obj)
			if err != nil {
				panic(err)
			}
		}(obj)
	}
}

Log

2019-11-08 09:57:24.5975 +0800 CST m=+0.749429025  result:  1
2019-11-08 09:57:24.597515 +0800 CST m=+0.749444445  result:  1
2019-11-08 09:57:24.59753 +0800 CST m=+0.749459549  result:  1
2019-11-08 09:57:24.597543 +0800 CST m=+0.749471943  result:  1
2019-11-08 09:57:24.597556 +0800 CST m=+0.749485330  result:  1
2019-11-08 09:57:24.597572 +0800 CST m=+0.749500902  result:  1
2019-11-08 09:57:24.597587 +0800 CST m=+0.749515746  result:  1
2019-11-08 09:57:24.597608 +0800 CST m=+0.749537522  result:  1
2019-11-08 09:57:24.597629 +0800 CST m=+0.749558045  result:  1
2019-11-08 09:57:24.597639 +0800 CST m=+0.749568376  result:  1
2019-11-08 09:57:24.597652 +0800 CST m=+0.749580667  result:  1
2019-11-08 09:57:24.597664 +0800 CST m=+0.749592752  result:  1
2019-11-08 09:57:24.597676 +0800 CST m=+0.749604811  result:  1
2019-11-08 09:57:24.597688 +0800 CST m=+0.749617130  result:  1
2019-11-08 09:57:24.5977 +0800 CST m=+0.749629502  result:  1
2019-11-08 09:57:24.597713 +0800 CST m=+0.749641599  result:  1
2019-11-08 09:57:24.597724 +0800 CST m=+0.749653596  result:  1
2019-11-08 09:57:24.597736 +0800 CST m=+0.749665538  result:  1
2019-11-08 09:57:24.597748 +0800 CST m=+0.749677438  result:  1
2019-11-08 09:57:24.597761 +0800 CST m=+0.749689620  result:  1
2019-11-08 09:57:24.597773 +0800 CST m=+0.749701772  result:  1
2019-11-08 09:57:24.597785 +0800 CST m=+0.749713650  result:  1
2019-11-08 09:57:24.597797 +0800 CST m=+0.749725604  result:  1
2019-11-08 09:57:24.597809 +0800 CST m=+0.749737630  result:  1
2019-11-08 09:57:24.597821 +0800 CST m=+0.749749838  result:  1
2019-11-08 09:57:24.597834 +0800 CST m=+0.749763114  result:  1
2019-11-08 09:57:24.597848 +0800 CST m=+0.749777219  result:  1
2019-11-08 09:57:24.597861 +0800 CST m=+0.749789852  result:  1
2019-11-08 09:57:24.598505 +0800 CST m=+0.750434037  result:  1
2019-11-08 09:57:24.598522 +0800 CST m=+0.750451430  result:  1
2019-11-08 09:57:24.598539 +0800 CST m=+0.750467751  result:  1
# blocked in BorrowObject

Questions

Hi, I am using go-commons-pool as the implementation of thread pools in my project.

The codes upper show how I am using it. But you can find the program blocked in func BorrowObject.

Then I debugged the source code. The trace is:

ReturnObject --> AddFirst --> linkFirst --> q.notEmpty.Signal() --> case cond.signal <- 1:

If cond.signal is not writable which is caused by that nobody is waiting on this unbuffered channel to read, this signal will be dropped.
Right after that, BorrowObject wait on q.notEmpty and nobody will signal it because of dropped signals under the config pc.MaxTotal = 1 . The trace is:

borrowObject --> PollFirstWithContext --> interrupt = q.notEmpty.Wait(ctx) -- > case _, ok := <-ch:

Is the way I am using is wrong or indeed the bug it is?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions