Skip to content

Commit 4b84090

Browse files
Potential Race Condition Fix - OS Rename & Chmod
1 parent a8c894f commit 4b84090

File tree

1 file changed

+19
-4
lines changed

1 file changed

+19
-4
lines changed

Diff for: gitdb/db/loose.py

+19-4
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
import tempfile
5555
import os
5656
import sys
57+
import time
5758

5859

5960
__all__ = ('LooseObjectDB', )
@@ -205,7 +206,7 @@ def store(self, istream):
205206
# END assure target stream is closed
206207
except:
207208
if tmp_path:
208-
os.remove(tmp_path)
209+
remove(tmp_path)
209210
raise
210211
# END assure tmpfile removal on error
211212

@@ -228,9 +229,23 @@ def store(self, istream):
228229
rename(tmp_path, obj_path)
229230
# end rename only if needed
230231

231-
# make sure its readable for all ! It started out as rw-- tmp file
232-
# but needs to be rwrr
233-
chmod(obj_path, self.new_objects_mode)
232+
# Ensure rename is actually done and file is stable
233+
# Retry up to 10 times - exponential wait & retry in ms.
234+
for exp_backoff in [1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289]:
235+
with suppress(PermissionError):
236+
# make sure its readable for all ! It started out as rw-- tmp file
237+
# but needs to be rwrr
238+
chmod(obj_path, self.new_objects_mode)
239+
break
240+
time.sleep(exp_backoff/1000.0)
241+
else:
242+
raise PermissionError(
243+
"Impossible to apply `chmod` to file {}".format(obj_path)
244+
)
245+
246+
# Cleanup
247+
with suppress(FileNotFoundError):
248+
remove(tmp_path)
234249
# END handle dry_run
235250

236251
istream.binsha = hex_to_bin(hexsha)

0 commit comments

Comments
 (0)