pariz / gountries

Gountries provides: Countries (ISO-3166-1), Country Subdivisions(ISO-3166-2), Currencies (ISO 4217), Geo Coordinates(ISO-6709) as well as translations, country borders and other stuff exposed as struct data.
MIT License
408 stars 67 forks source link

protect query init with sync.Once #39

Closed sebnyberg closed 2 years ago

sebnyberg commented 3 years ago

This PR fixes a race condition in the query initialization that can (and does) cause a concurrent map access panic.

sebnyberg commented 3 years ago

Reproduce with go run -race main.go:

package main

import (
    "sync"

    "github.com/pariz/gountries"
)

func main() {
    var wg sync.WaitGroup
    wg.Add(2)
    go gountries.New()
    go gountries.New()
    wg.Wait()
}
==================
WARNING: DATA RACE
Write at 0x0000014da520 by goroutine 8:
  github.com/pariz/gountries.NewFromPath()
      /Users/seb/go/pkg/mod/github.com/pariz/gountries@v0.0.0-20200430155801-1c6a393df9c7/setup.go:25 +0x11c
  github.com/pariz/gountries.New()
      /Users/seb/go/pkg/mod/github.com/pariz/gountries@v0.0.0-20200430155801-1c6a393df9c7/setup.go:18 +0x9d

Previous write at 0x0000014da520 by goroutine 7:
  [failed to restore the stack]

Goroutine 8 (running) created at:
  main.main()
      /Users/seb/code/github/sebnyberg/gountries/cmd/main.go:13 +0xb4

Goroutine 7 (running) created at:
  main.main()
      /Users/seb/code/github/sebnyberg/gountries/cmd/main.go:12 +0x9c
==================

Side-note: TestMain must be removed to re-produce the race in a test setting.

sebnyberg commented 3 years ago

@pariz Could you please take a look? It's a very small change, and having the init panic during concurrent use is a serious issue.

pariz commented 2 years ago

Hi! This has been resolved by another PR. Thanks for your contribution and sorry for an extremely late response