FYI:   It is possible for `done` to never be sent to.  For example consider 
the following sequence:

goroutine:   ch <- 1
main: <- 1
main: run defer
main: fin = atomic load
goroutine: atomic store
main: not 1, return


On Friday, August 18, 2017 at 11:13:36 AM UTC-7, bill....@talentinc.com 
wrote:
>
> Hi,
>
> https://play.golang.org/p/lR6_mxSjtb
>
> I have two long running things to do, I'd like to do them in parallel, 
> then sync up at the end. I've written it as a function which gets one thing 
> done, and which backgrounds the second thing with a goroutine. Thing one 
> has a lot of reasons to exit early, and I need to signal those to thing two 
> so that the go routine can exit cleanly and not create a goroutine leak. 
> Standard fare, usually solved by introducing a channel and a select 
> statement. I want to signal done for early exits, including panics,  so I 
> thought I would write to the done channel in a defer block. That caused a 
> problem, because in the happy case, both the foreground and the background 
> routines are finished, the done channel has no reader, so writing to it in 
> the defer block causes "fatal error: all goroutines are asleep - deadlock!" 
> So I introduced a new boolean variable ("clean_finish") that is false until 
> the background job completes, and which is tested in the defer block before 
> writing to the done channel. Is there anything wrong with my approach? You 
> can see the code in the playground link above, or down below.
>
>
> package main
>
> import (
> "sync/atomic"
> "fmt"
> "time"
> )
>
> func main() {
> ch := make(chan int)
> done := make(chan struct{})
> var clean_finish uint32
> defer func() { 
> fin := atomic.LoadUint32(&clean_finish)
> if fin != 1 {
> done <- struct{}{}
> }
> }()
> go func() {
> defer func() {
> fmt.Println("we're done here")
> }()
> select {
> case <-time.After(time.Second * 1):
> ch <- 1
> atomic.StoreUint32(&clean_finish, 1)
> case <- done:
> fmt.Println("early exit")
> }
> }()
> panic("bye") // comment this out to see normal behavior
> n := <- ch
> fmt.Printf("n: %v\n", n)
> }
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to