From 9f7adb2614554c309c8370bb477474787b33f253 Mon Sep 17 00:00:00 2001 From: TLSM Date: Sun, 6 Nov 2022 00:48:54 -0400 Subject: [PATCH] Fix recent CPU spikes from image encoding. Certain animated images take an exceedingly long time (~minutes) to encode to WEBP using method=6. Such a file was obtained, and it encoded significantly faster using method=5 and somehow turned out smaller than the result generated with method=6. We switch now to use method=5 so we stop getting occasional massive increases in CPU load when multiple users upload animations at the same time. Additionally, a timeout was added to the ImageMagick subprocess just in case there are even more pathological files in the future. Better to error out than have to get someone to kill the process. --- files/helpers/const.py | 1 + files/helpers/media.py | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/files/helpers/const.py b/files/helpers/const.py index 52cb39a77..dcffc6cf0 100644 --- a/files/helpers/const.py +++ b/files/helpers/const.py @@ -454,6 +454,7 @@ MAX_IMAGE_AUDIO_SIZE_MB = 8 MAX_IMAGE_AUDIO_SIZE_MB_PATRON = 16 MAX_VIDEO_SIZE_MB = 32 MAX_VIDEO_SIZE_MB_PATRON = 64 +MAX_IMAGE_CONVERSION_TIMEOUT = 15 # seconds ANTISPAM_BYPASS_IDS = () diff --git a/files/helpers/media.py b/files/helpers/media.py index 46ff5c10f..4a3211c85 100644 --- a/files/helpers/media.py +++ b/files/helpers/media.py @@ -127,15 +127,18 @@ def process_image(filename=None, resize=0, trim=False, uploader=None, patron=Fal abort(413, f"Max image/audio size is {MAX_IMAGE_AUDIO_SIZE_MB} MB ({MAX_IMAGE_AUDIO_SIZE_MB_PATRON} MB for paypigs)") with Image.open(filename) as i: - params = ["convert", "-coalesce", filename, "-quality", "88", "-define", "webp:method=6", "-strip", "-auto-orient"] + params = ["convert", "-coalesce", filename, "-quality", "88", "-define", "webp:method=5", "-strip", "-auto-orient"] if trim and len(list(Iterator(i))) == 1: params.append("-trim") if resize and i.width > resize: params.extend(["-resize", f"{resize}>"]) params.append(filename) - subprocess.run(params) - + try: + subprocess.run(params, timeout=MAX_IMAGE_CONVERSION_TIMEOUT) + except subprocess.TimeoutExpired: + abort(413, ("An uploaded image took too long to convert to WEBP. " + "Consider uploading elsewhere.")) if resize: if os.stat(filename).st_size > MAX_IMAGE_SIZE_BANNER_RESIZED_KB * 1024: