Fix race condition in thumbnail candidate generation
Concurrent requests for the same course's thumbnail (e.g. the Precompute background scan overlapping an ordinary page load) shared fixed candidate filenames, so one request's cleanup could delete a temp file the other was still using, crashing with ENOENT. Candidate filenames are now unique per call. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
2026-08-25 00:26 UTC — Fix race condition in thumbnail candidate generation
|
||||
2026-08-25 00:20 UTC — Add autoplay, progress rings, duplicate-lesson detection, title-card thumbnails
|
||||
2026-08-24 23:22 UTC — Add Favorites, storage drill-down, shortcuts, and What's New
|
||||
2026-08-24 19:00 UTC — Fix video resize handle drifting off-screen
|
||||
|
||||
@@ -1 +1 @@
|
||||
2026-08-25 00:20 UTC — autoplay, progress rings, duplicate lessons, title-card thumbnails
|
||||
2026-08-25 00:26 UTC — fix race condition in thumbnail candidate generation
|
||||
|
||||
+6
-1
@@ -952,9 +952,14 @@ def _generate_course_thumbnail(course_dir: Path) -> Optional[str]:
|
||||
best_candidate = None
|
||||
best_size = -1
|
||||
candidate_paths = []
|
||||
# Unique per call (not just per offset) so two concurrent requests for
|
||||
# the same course - e.g. the Precompute background scan racing an
|
||||
# ordinary page load that also misses the cache - never write or clean
|
||||
# up each other's candidate files out from under one another.
|
||||
run_id = uuid.uuid4().hex[:8]
|
||||
try:
|
||||
for i, offset in enumerate(candidate_offsets):
|
||||
candidate_path = course_dir / f'.offlineu_thumbnail_candidate_{i}.jpg'
|
||||
candidate_path = course_dir / f'.offlineu_thumbnail_candidate_{run_id}_{i}.jpg'
|
||||
candidate_paths.append(candidate_path)
|
||||
try:
|
||||
result = subprocess.run(
|
||||
|
||||
Reference in New Issue
Block a user