Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

go routines not working as expected #1498

Closed
brucengdev opened this issue Dec 26, 2022 · 2 comments · Fixed by #1501
Closed

go routines not working as expected #1498

brucengdev opened this issue Dec 26, 2022 · 2 comments · Fixed by #1501
Labels
area/core bug Something isn't working
Milestone

Comments

@brucengdev
Copy link

The following program sample.go triggers an unexpected result

package main

import (
	"encoding/json"
	"fmt"
	"strconv"
	"sync"
)

func main() {
	hits := make([]string, 3)
	for i, _ := range hits {
		hits[i] = string("hit" + strconv.Itoa(i))
	}

	bytes, _ := json.Marshal(hits)
	fmt.Println("hits: " + string(bytes))

	var wg sync.WaitGroup
	for _, hit := range hits {
		wg.Add(1)
		go func(hit string) {
			fmt.Println("hit = " + hit)
			defer wg.Done()
		}(hit)
	}
	wg.Wait()
}

Expected result

hits: ["hit0","hit1","hit2"]
hit = hit2
hit = hit0
hit = hit1

Got

hits: ["hit0","hit1","hit2"]
hit = hit2
hit = hit2
hit = hit2

Yaegi Version

0.14.3

Additional Notes

No response

@mpl
Copy link
Collaborator

mpl commented Dec 26, 2022

Tbh, I'm really puzzled that we could have this bug. I could have sworn we have a regression test for this pattern, but here we are.

Interestingly, if you use the "other version" of this pattern (I prefer your version, but I believe most people use the version below), then yaegi behaves correctly:

package main

import (
	"encoding/json"
	"fmt"
	"strconv"
	"sync"
)

func main() {
	hits := make([]string, 3)
	for i, _ := range hits {
		hits[i] = string("hit" + strconv.Itoa(i))
	}

	bytes, _ := json.Marshal(hits)
	fmt.Println("hits: " + string(bytes))

	var wg sync.WaitGroup
	for _, hit := range hits {
		hit := hit
		wg.Add(1)
		go func() {
			fmt.Println("hit = " + hit)
			defer wg.Done()
		}()
	}
	wg.Wait()
}

@mpl mpl added bug Something isn't working area/core labels Dec 26, 2022
@brucengdev
Copy link
Author

brucengdev commented Dec 26, 2022

Thanks, I'm using a workaround, using a counter to reference array elements.
It seems that when a variable is passed as a parameter to the go routine, if the variable is changed outside by the range operation, the local variable in the go routines get updated, too. Which makes all go routines end up using the same value. Just a wild guess.

        var wg sync.WaitGroup
        i := 0
	for i < len(hits) {
		wg.Add(1)
		go func(hit string) {
			fmt.Println("hit = " + hit)
			defer wg.Done()
		}(hits[i])
                i++
	}
	wg.Wait()

@traefiker traefiker added this to the v0.15.x milestone Jan 16, 2023
traefiker pushed a commit that referenced this issue Jan 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/core bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants