Image style streaming doesn't work with D10.1

Created on 9 November 2023, 8 months ago
Updated 29 December 2023, 6 months ago

Problem/Motivation

I have just upgraded one of the websites I maintain to Drupal 10.1.8 and I faced an issue that the image style is generated and uploaded to the Blob Storage, but the server (php7.1 + nginx) returned with gateway timeout on the [...]/azblob/files/styles/thumbnail/azblob/media/image/[...].jpg url it could not stream it to the browser.

The problem is that the BinaryFileResponse what is used by the AzBlobFsImageStyleDownloadController is refactored in Symfony 5.4 and instead of stream_copy_to_stream is uses fopen, fseek, fwrite, feof and fclose php methods. Most of these are implemented properly in the AzBlobFsStream, but the stream_eof uses the eof method of the SreamDecoratorTrait. In the AzBlobFsStream::stream_open a new Stream object is created and assigned to the StreamDecoratorTrait::$stream property, but the Content Stream of the Blob is assigned to the AzBlobFsStream::$temporaryFileHandle property.

$this->stream = new Stream(fopen('php://temp', $mode));
...
        $blob = $this->client->getBlob($this->container, $target);
        $this->temporaryFileHandle = $blob->getContentStream();

Since the AzBlobFsStream::stream_eof calls the StreamDecoratorTrait::eof and its implementation is:
return $this->stream->eof(); it will never be TRUE.

Steps to reproduce

Install Drupal 10.1.8
Enable az_blob_fs module
Set the blob storage config and webserver properly (to handle image styles)
Create an image field
Try to upload an image
The image is uploaded to the blob storage and the image style is also created and uploaded to the blob storage, but the resized thumbnail does not appear in the browser.

Proposed resolution

The easiest way to update the AzBlobFsStream::stream_eof from return $this->stream->eof(); to return feof($this->temporaryFileHandle); and the image style download controller will work properly.

The better solution would be to create a new Stream object with the $blob->getContentStream() then call the method of StreamDecoratorTrait in methods of the AzBlobFsStream. It is worth considering this refactor.

πŸ› Bug report
Status

RTBC

Version

2.0

Component

Code

Created by

πŸ‡­πŸ‡ΊHungary pauger

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @pauger
  • πŸ‡­πŸ‡ΊHungary pauger

    Patch attached.

  • Status changed to Needs review 8 months ago
  • πŸ‡­πŸ‡ΊHungary pauger
  • πŸ‡«πŸ‡·France ckhalilo

    This patch is working for me.
    Without this patch in my env PHP 8.2, I have 200% CPU and Memory limits is reaching more 190%.

    Thank you.

  • Status changed to RTBC 6 months ago
  • πŸ‡ΊπŸ‡ΈUnited States Chris Burge

    I just had a customer run into this. Immediately upon upgrading to Drupal 10.1.7, we observed CPU maxed out at 100%, which crashed their hosting stack. The following errors were showing up in the logs:

    [20-Dec-2023 12:08:07 America/Los_Angeles] PHP Fatal error: Maximum execution time of 300 seconds exceeded in /mnt/www/html/[omitted]/docroot/modules/contrib/az_blob_fs/src/StreamWrapper/AzBlobFsStream.php on line 592 request_id="v-c9248472-9f72-11ee-9656-cb202b0e421b"

    [20-Dec-2023 14:38:51 America/Los_Angeles] PHP Fatal error: Maximum execution time of 300 seconds exceeded in /mnt/www/html/[omitted]/docroot/modules/contrib/az_blob_fs/src/StreamWrapper/AzBlobFsStream.php on line 410 request_id="v-d824acee-9f87-11ee-a31c-4bdba48a437c"

    Since the method checking end of file never returns true, it looks like the process just hangs until it eventually times out at 300 seconds (5 minutes). That can quickly lead to proc exhaustion.

    Following deployment of patch #2, the errors ceased and application performance returned to normal.

    I'm also upgrading the status to critical since this bug has been observed causing application downtime.

Production build 0.69.0 2024