Multiple goroutine timeout for waitgroup not working

699 views
Skip to first unread message

desaia...@gmail.com

unread,
Jan 8, 2017, 2:23:23 AM1/8/17
to golang-nuts

Can you please help to correct below program where timeout not seems working

Work 1 - have 1 second
Work 2 - have 3 second
Total Timeout - 2 sec

program wait for entire 3 seconds and return both values rather than value from Work 1

Program >

package main

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


type TestStruct struct {
Name string
}

func main() {

wg := &sync.WaitGroup{}
messges := make(chan *TestStruct, 1)

wg.Add(1)
go Work1(messges, wg, "1")
wg.Add(1)
go Work2(messges, wg, "2")

monitorWorker(wg, messges)

messgesResponse := make(chan []*TestStruct)
go GetWorkerValues(messges, messgesResponse)

headers := make([]*TestStruct, 0)
headers = <-messgesResponse

fmt.Printf("len > %s\n", len(headers))

for i:=0;i<len(headers);i++ {
fmt.Printf("Name > %s\n", headers[i].Name)
}
}



func monitorWorker(wg *sync.WaitGroup, cs chan *TestStruct) {
go func() {
defer close(cs)
wg.Wait()
}()

select {
case <-time.After(2 * time.Second):
return
}
}
func Work1(message chan *TestStruct, wg *sync.WaitGroup, tokenNumber string)  {
defer wg.Done()

v1 := new(TestStruct)
v1.Name = tokenNumber
time.Sleep(1 * time.Second)

message <- v1
fmt.Printf("finished %s\n", tokenNumber)
}

func Work2(message chan *TestStruct, wg *sync.WaitGroup, tokenNumber string)  {
defer wg.Done()

v1 := new(TestStruct)
v1.Name = tokenNumber
time.Sleep(1 * time.Second)

message <- v1

fmt.Printf("finished %s\n", tokenNumber)
}


func GetWorkerValues(cs <-chan *TestStruct, response chan<- []*TestStruct) {
var val []*TestStruct
for header := range cs {
val = append(val, header)
}
response <- val
}


Thanks,

Abhi

Abhijit Desai

unread,
Jan 8, 2017, 6:39:48 AM1/8/17
to Sairam Kunala, golang-nuts
Thanks for the reply Sairam

Problem is if I change Work2 time => 3 sec then that work should get timeout but program still returning it

func Work2(message chan *TestStruct, wg *sync.WaitGroup, tokenNumber string)  {
defer wg.Done()

v1 := new(TestStruct)
v1.Name = tokenNumber
time.Sleep(3 * time.Second)

message <- v1

fmt.Printf("finished %s\n", tokenNumber)
}

Rgds,

Abhi

On Sun, Jan 8, 2017 at 1:39 PM, Sairam Kunala <sairam...@gmail.com> wrote:
The ran the code on play, seems to come out within 2 seconds.


--
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+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


John Souvestre

unread,
Jan 8, 2017, 6:39:56 AM1/8/17
to golang-nuts

What do you see when you run it?  I see:

 

   finished 1

   finished 2

  len > %!s(int=2)   ç Using a string format for an int

   Name > 1

   Name > 2

 

Ø  Work 2 - have 3 second

 

I’m not sure exactly what you are trying to do, but I suspect that changing “messges” to hold 2 items might make it work.

 

      messges := make(chan *TestStruct, 2)

 

I’m guessing, but I suspect that you didn’t realize that if Work1 runs first, then Work2 will block since the channel is full (or until you close it).

 

John

    John Souvestre - New Orleans LA

--

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...@googlegroups.com.

desaia...@gmail.com

unread,
Jan 8, 2017, 6:48:02 AM1/8/17
to golang-nuts
hi John

Thanks for the reply

sorry 

I mean Work2 takes => 3 seconds
work1 takes => 1 seconds

Wait group timeout is => 1 seconds

It is expected that only Work1 should get done and Work 2 should get timeout which is not happening

Waitgroup waits for both work.. program doing something wrong

func Work2(message chan *TestStruct, wg *sync.WaitGroup, tokenNumber string)  {
defer wg.Done()

v1 := new(TestStruct)
v1.Name = tokenNumber
time.Sleep(3 * time.Second)

message <- v1

fmt.Printf("finished %s\n", tokenNumber)
}

Thanks,

Abhi

John Souvestre

unread,
Jan 8, 2017, 7:10:01 AM1/8/17
to golang-nuts

Hi Abhi.

 

I believe that the wait group timeout (in monitorWorker) was set to 2 seconds in the code you posted.

 

I put a debugging print in the timeout case, and it is taking place.

 

What were you expecting to see?

John Souvestre

unread,
Jan 8, 2017, 7:13:00 AM1/8/17
to golang-nuts

Hi again.

 

Did you perhaps intend to make the call to monitorWorker() as a goroutine?  That would let it run in parallel with the rest of main.

 

John

    John Souvestre - New Orleans LA

 

From: John Souvestre [mailto:Jo...@Souvestre.com]
Sent: 2017 January 08, Sun 06:10
To: 'golang-nuts'
Subject: RE: [go-nuts] Multiple goroutine timeout for waitgroup not working

 

Hi Abhi.

 

I believe that the wait group timeout (in monitorWorker) was set to 2 seconds in the code you posted.

 

I put a debugging print in the timeout case, and it is taking place.

 

What were you expecting to see?

 

John



    John Souvestre - New Orleans LA


Sent: 2017 January 08, Sun 05:48
To: golang-nuts

desaia...@gmail.com

unread,
Jan 8, 2017, 7:24:09 AM1/8/17
to golang-nuts
hi John

I am expecting work2 should not include in

headers = <-messgesResponse

so output of below should be Len = 1 and should print only work 1 only and not 2 ( as work 2 is timed out )

 

            fmt.Printf("len > %s\n", len(headers))

 

            for i:=0;i<len(headers);i++ {

                        fmt.Printf("Name > %s\n", headers[i].Name)

            }


basically workgroup timeout doesnt close the timeout works

            select {

                        case <-time.After(2 * time.Second): //This works but dont stop the work2

                                    return

            }


Do I need to explicitly close them in

            select {

                        case <-time.After(2 * time.Second):

                                    close(cs)

                                    return

            }


Thanks for the help

Rgds,

Abhi 

desaia...@gmail.com

unread,
Jan 8, 2017, 7:55:10 AM1/8/17
to John Souvestre, golang-nuts
Hi John

I have taken code from one of the site  to make it work for me

In real program, spawning 100 goroutine to do the work with timeout 2 sec but found that entire program takes time which is equal to time taken by routine which finishes last irrespective of workgroup timeout

So need help to fix program so that timeout will force to close and merge the work done by all routines within 2 sec where few routines will return work where as few will not because of timeout

Thanks

Abhi
--
You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/o0DYWZIlmvs/unsubscribe.
To unsubscribe from this group and all its topics, send an email to golang-nuts...@googlegroups.com.

John Souvestre

unread,
Jan 8, 2017, 8:06:18 AM1/8/17
to golang-nuts

Hi Abhi.

 

I believe that your logic is faulty.  The timeout does take place – but it doesn’t really do what you wanted, I think.

 

GetWorkerValues isn’t going to send it’s info because the “range cs” can’t finish until the channel is closed.  The channel is not closed until both workers are finished – timeout or not, thus it always contains the info for both workers.

desaia...@gmail.com

unread,
Jan 8, 2017, 8:10:41 AM1/8/17
to John Souvestre, golang-nuts
Hi John

Can you please help me to apply correct logic to achieve it

Haven't found any solution on the net. All articles are talking about only 1 routine timeout and not multiple

Thank you very much

Rgds

Abhi
You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/o0DYWZIlmvs/unsubscribe.
To unsubscribe from this group and all its topics, send an email to golang-nuts...@googlegroups.com.

John Souvestre

unread,
Jan 8, 2017, 8:27:03 AM1/8/17
to golang-nuts

Hi Abhi.

 

I’m thinking something like this might do the job.  Call monitorWorker(wg, done) as a goroutine and change it to do just the wg.Wait then send a signal on the “done” channel.

 

Next, start a goroutine which signals on a “timeout” channel if the timeout is exceeded.

 

Finally, change GetWorkerValues to be an endless loop containing a select with three cases: “<-cs” (add new value to array), “<-done” (break), and “<-timeout” (break).  After the loop, send the array.

 

John

    John Souvestre - New Orleans LA

 

John Souvestre

unread,
Jan 8, 2017, 9:48:03 AM1/8/17
to golang-nuts

Hi Abhi.

 

An afterthought:  For the “done” case, add a check to clear out any “cs” values which might come in just before the “done” signal.  You won’t need to worry about this in the “timeout” case.

 

John

    John Souvestre - New Orleans LA

 

From: John Souvestre [mailto:Jo...@Souvestre.com]
Sent: 2017 January 08, Sun 07:27
To: 'golang-nuts'
Subject: RE: [go-nuts] Multiple goroutine timeout for waitgroup not working

 

Hi Abhi.

 

I’m thinking something like this might do the job.  Call monitorWorker(wg, done) as a goroutine and change it to do just the wg.Wait then send a signal on the “done” channel.

 

Next, start a goroutine which signals on a “timeout” channel if the timeout is exceeded.

 

Finally, change GetWorkerValues to be an endless loop containing a select with three cases: “<-cs” (add new value to array), “<-done” (break), and “<-timeout” (break).  After the loop, send the array.

 

John



    John Souvestre - New Orleans LA

Sent: 2017 January 08, Sun 07:10
To: John Souvestre

Sairam Kunala

unread,
Jan 8, 2017, 1:17:46 PM1/8/17
to desaia...@gmail.com, golang-nuts
The ran the code on play, seems to come out within 2 seconds.

On Sun, Jan 8, 2017 at 12:53 PM, <desaia...@gmail.com> wrote:

--
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+unsubscribe@googlegroups.com.

desaia...@gmail.com

unread,
Jan 8, 2017, 10:14:28 PM1/8/17
to golang-nuts
Thanks very much John

Let me check

Rgds,

Abhi

On Sunday, January 8, 2017 at 8:18:03 PM UTC+5:30, John Souvestre wrote:

Hi Abhi.

 

An afterthought:  For the “done” case, add a check to clear out any “cs” values which might come in just before the “done” signal.  You won’t need to worry about this in the “timeout” case.

Reply all
Reply to author
Forward
0 new messages