mirror of
https://github.com/dutchcoders/transfer.sh.git
synced 2026-02-03 14:13:26 +00:00
Race condition crash in CheckMetadata locking: fatal error: concurrent map read and map write
#170
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @JustAnotherArchivist on GitHub.
Our transfer.sh server crashed today with the following traceback (only the relevant lines, paths redacted):
The line numbers differ from the code in this repository as I'm running a modified code, but I'm all but certain that these modifications are unrelated to the crash. From the bottom, the corresponding lines in the current master code are:
1594f95abf/server/handlers.go (L986)1594f95abf/server/handlers.go (L660)1594f95abf/server/handlers.go (L643-L644)Note that the traceback is the same except for the one line difference in
Lock, with one goroutine trying to create a mutex unders.locks[key](line 632 in my code, 644 in master) and the other trying to access it (line 631 in my code, 643 in master).This happened on a
GETshortly after the upload of a new file. The upload was successful, and the URL was automatically shared and then accessed immediately around a dozen times in parallel and very quick succession (5 accesses within 100 ms, then another 5 in the following 200 ms plus a few more after, according to the Caddy logs). However, these kind of requests happen all the time on our instance and has never led to crashes before. transfer crashed before returning a response for any of the requests as far as I can tell.I tried to reproduce this by running parallel requests against transfer (with a tool built in Python around aiohttp) but did not manage to trigger it that way. Perhaps the requests weren't quite quick enough. I haven't had time to set up and try other methods.
My interpretation is that this is a race condition in the locking code: two requests were trying to work with the metadata lock at the same time, one trying to create the mutex under
s.locks[key], the other trying to access that key, but becauses.locksis a simple map, such simultaneous actions aren't possible.@paolafrancesca commented on GitHub:
@JustAnotherArchivist makes sense, I will try to check in the weekend, probably need to change
s.lockswith https://golang.org/pkg/sync/#Map