Golang Map Key Changed after reading

Hey,
i’m trying to record the regions where successful requests come from and i get the following bug consistently, but only running on fly.io:
when i’m requesting the regions count (/regions) i get on the first request the correct response. when i’m rerequesting the regions i still get the correct response. but if a new successful request was made (ofc /regions is not counted) and i’m then requesting regions again the key of for example “fra” is changed to “max” (every time). but this only occurs when requesting them via http. and it does not matter wether or not i’m sending json or strings as response. and the key is not only changed in the response but in the map itself.
the bug does not appear on my local machine, regardless of how i run the programm (“raw” or docker"). I even linked the binary statically. it also does not matter who compiled the programm. the bug appears regardless of compiling it (as docker image) on my drone server or letting it compile by fly.io

my code: gitea-attachements-proxy/main.go at main - gitea-attachements-proxy - Git: entr0py.de

That’s weird. We’re not doing anything clever with the binary or kernel, your app is running no a Linux kernel in a KVM container.

The only different I can think of other than kernel is the CPU count. The smallest VM we run only has one CPU, so concurrent code can behave differently there than on your local machine (which probably has multiple CPUs). If you’re on a Linux machine, you can emulate this behavior with cgroups. If you’re not, the best you might be able to do is runtime.GOMAXPROCS(1).

I’ve tested this and this does not make any difference :frowning:

I quickly checked the code and it might be a race condition. The handler for /regions only has a lock inside regionCounter.getRegionCount(), but it’s reading from the map outside the lock. That may not be the exact cause, but as Kurt suggested, it’s more likely a race condition than an issue with the runtime.

fwiw this is a great use case for the sync.Map package which handles locking internally so you don’t need a mutex.

The handler for /regions only has a lock inside regionCounter.getRegionCount(), but it’s reading from the map outside the lock.

ok yes, this happened when i tried $things … but even when i’m locking where i’m actually reading the map changes.