sourcegraph / conc

Better structured concurrency for go

Home Page:https://about.sourcegraph.com/blog/building-conc-better-structured-concurrency-for-go

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

deadlock!

Phuong39 opened this issue · comments

i tried Pool_WithCancelOnError but got deadlock , how fix it?
, thank


package main

import (
	"context"
	"errors"
	"fmt"

	"github.com/sourcegraph/conc/pool"
)

func main() {

	ExampleContextPool_WithCancelOnError()
}

func ExampleContextPool_WithCancelOnError() {
	p := pool.New().
		WithMaxGoroutines(10).
		WithContext(context.Background()).
		WithCancelOnError()
	for i := 0; i < 90; i++ {
		i := i
		p.Go(func(ctx context.Context) error {
			if i == 10 {
				return errors.New("I will cancel all other tasks!")
			}
			<-ctx.Done()
			return nil
		})
	}
	err := p.Wait()
	fmt.Println(err)
	// Output:
	// I will cancel all other tasks!
}

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [select]:
github.com/sourcegraph/conc/pool.(*Pool).Go(0xc000116600, 0xc0000ac5e8)        
        D:/gopath/src/github.com/sourcegraph/conc/pool/pool.go:54 +0x95        
github.com/sourcegraph/conc/pool.(*ErrorPool).Go(0xc000116600, 0xc0000ac5d0)   
        D:/gopath/src/github.com/sourcegraph/conc/pool/error_pool.go:29 +0x7a  
github.com/sourcegraph/conc/pool.(*ContextPool).Go(0xc000116600, 0xc0000af250) 
        D:/gopath/src/github.com/sourcegraph/conc/pool/context_pool.go:25 +0x7a
main.ExampleContextPool_WithCancelOnError()
        /pool_t50.go:23 +0xc6 
main.main()
        /pool_t50.go:13 +0x17 

goroutine 21 [chan receive]:
main.ExampleContextPool_WithCancelOnError.func1({0xa8ab90?, 0xc000092440?})    
        /pool_t50.go:27 +0x69 
github.com/sourcegraph/conc/pool.(*ContextPool).Go.func1()
        D:/gopath/src/github.com/sourcegraph/conc/pool/context_pool.go:26 +0x2e
github.com/sourcegraph/conc/pool.(*ErrorPool).Go.func1()
        D:/gopath/src/github.com/sourcegraph/conc/pool/error_pool.go:30 +0x29  
github.com/sourcegraph/conc/pool.(*Pool).worker(0x0?)
        D:/gopath/src/github.com/sourcegraph/conc/pool/pool.go:154 +0x7a       
github.com/sourcegraph/conc/panics.(*Catcher).Try(0x0?, 0x0?)
        D:/gopath/src/github.com/sourcegraph/conc/panics/panics.go:23 +0x53    
github.com/sourcegraph/conc.(*WaitGroup).Go.func1()
        D:/gopath/src/github.com/sourcegraph/conc/waitgroup.go:32 +0x65
created by github.com/sourcegraph/conc.(*WaitGroup).Go
        D:/gopath/src/github.com/sourcegraph/conc/waitgroup.go:30 +0x85

        D:/gopath/src/github.com/sourcegraph/conc/waitgroup.go:32 +0x65
created by github.com/sourcegraph/conc.(*WaitGroup).Go
        D:/gopath/src/github.com/sourcegraph/conc/waitgroup.go:30 +0x85



This is not really an issue with this package firstly the context you have passed to your Pool is using a context.Background() which will never be "Done" (never sends anything to done channel).
Secondly you should use select to mitigate this issue.

package main

import (
	"context"
	"errors"
	"fmt"

	"github.com/sourcegraph/conc/pool"
)

func main() {

	ExampleContextPool_WithCancelOnError()
}

func ExampleContextPool_WithCancelOnError() {
	p := pool.New().
		WithMaxGoroutines(10).
		WithContext(context.Background()).
		WithCancelOnError()
	for i := 0; i < 90; i++ {
		i := i
		p.Go(func(ctx context.Context) error {
			if i == 10 {
				return errors.New("I will cancel all other tasks!")
			}

			select {
			case <-ctx.Done():
				return nil
			default:
				return nil
			}

		})
	}
	err := p.Wait()
	fmt.Println(err)
	// Output:
	// I will cancel all other tasks!
}

thanks,bro