Fix blocking stat() via is_file in image_upload (#122808)

This commit is contained in:
J. Nick Koston 2024-07-29 15:38:58 -05:00 committed by GitHub
parent fdab23c3f9
commit 1c03c83c0a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -220,18 +220,18 @@ class ImageServeView(HomeAssistantView):
hass = request.app[KEY_HASS] hass = request.app[KEY_HASS]
target_file = self.image_folder / image_id / f"{width}x{height}" target_file = self.image_folder / image_id / f"{width}x{height}"
if not target_file.is_file(): if not await hass.async_add_executor_job(target_file.is_file):
async with self.transform_lock: async with self.transform_lock:
# Another check in case another request already # Another check in case another request already
# finished it while waiting # finished it while waiting
if not target_file.is_file(): await hass.async_add_executor_job(
await hass.async_add_executor_job( _generate_thumbnail_if_file_does_not_exist,
_generate_thumbnail, target_file,
self.image_folder / image_id / "original", self.image_folder / image_id / "original",
image_info["content_type"], image_info["content_type"],
target_file, target_file,
(width, height), (width, height),
) )
return web.FileResponse( return web.FileResponse(
target_file, target_file,
@ -239,16 +239,18 @@ class ImageServeView(HomeAssistantView):
) )
def _generate_thumbnail( def _generate_thumbnail_if_file_does_not_exist(
target_file: pathlib.Path,
original_path: pathlib.Path, original_path: pathlib.Path,
content_type: str, content_type: str,
target_path: pathlib.Path, target_path: pathlib.Path,
target_size: tuple[int, int], target_size: tuple[int, int],
) -> None: ) -> None:
"""Generate a size.""" """Generate a size."""
image = ImageOps.exif_transpose(Image.open(original_path)) if not target_file.is_file():
image.thumbnail(target_size) image = ImageOps.exif_transpose(Image.open(original_path))
image.save(target_path, format=content_type.partition("/")[-1]) image.thumbnail(target_size)
image.save(target_path, format=content_type.partition("/")[-1])
def _validate_size_from_filename(filename: str) -> tuple[int, int]: def _validate_size_from_filename(filename: str) -> tuple[int, int]: