Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for vips intervention image backend #539

Merged
merged 3 commits into from
Aug 7, 2023

Conversation

forsdahl
Copy link
Contributor

The vips intervetion image backend isn't working right now, because InterventionBackend unlinks the temporary file too early. It is removed before the actual libvips commands are run against it, which makes them fail. The temporary file is removed in the destructor of InterventionBackend anyway, so this section is unnecessary.

@GuySartorelli
Copy link
Member

The temporary file is removed in the destructor of InterventionBackend anyway, so this section is unnecessary.

Could this cause storage problems if a single request (e.g. some dev/task) affects a large number of very big images?

@michalkleiner
Copy link
Contributor

Should be fine as long as we can be sure we have a new instance for every image.

@forsdahl
Copy link
Contributor Author

The only case I can see where this might be a problem is if the same image backend instance is used for several manipulations on different images (alhtough I don't see exactly the use case where that would happen). One thing that could be done is to make sure we unlink the temporary file if the image resource of the image backend is set to null (which happens at the end of an image manipulation), i.e. in setImageResource in InterventionBackend.

@forsdahl
Copy link
Contributor Author

Alternatively, PR #527 also fixes the issue with the vips backend. That PR removes the temporary file creation entirely, and always creates the image resource from the stream, which also works well for the vips driver. @christopherdarling can you have a look at that pull request and see if can be made to pass all tests?

@christopherdarling
Copy link
Contributor

@forsdahl yep - it's on my list just don't have much capacity right now

@kinglozzer
Copy link
Member

I’ve had a look at this PR and I’d be okay with merging it with the amend to setImageResource() described above.

The only case I can see where this might be a problem is if the same image backend instance is used for several manipulations on different images (alhtough I don't see exactly the use case where that would happen)

There’s certainly nothing out of the box that would do this, the ImageManipulation trait will create a new image backend for each image, nothing in there is static or shared between Image instances.

One thing that could be done is to make sure we unlink the temporary file if the image resource of the image backend is set to null (which happens at the end of an image manipulation), i.e. in setImageResource in InterventionBackend.

I think that’s a good idea. I’d also tweak setAssetContainer() to call setImageResource(null) just in case anyone is using the API directly.

We’re not doing any more minor releases of Silverstripe 4 and I don’t think we can really sneak this into a patch release so this will need to be retargeted. @GuySartorelli what do you think with regard to targeting this to 5? Target 2.0 and the 5.0.0 release, or target 2 and delay until 5.1.0?

@GuySartorelli
Copy link
Member

GuySartorelli commented Mar 29, 2023

Should probably target 2 - we're hoping to target the release candidate for 5.0 next week so it'd be cutting it a bit close for that I reckon.

@forsdahl
Copy link
Contributor Author

forsdahl commented Aug 4, 2023

Added the changes discussed above, namely to unlink the temporary file whenever the image resource is set to null.

Copy link
Member

@GuySartorelli GuySartorelli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Just one small change to make. Please also retarget this PR to the 1.13 branch (I said 2 above, but I'm okay with this being in a patch after further consideration. It is effectively a bug fix, and doesn't affect APIs or have any obvious regressions)

if ($image === null) {
// remove our temp file if it exists
if (file_exists($this->getTempPath() ?? '')) {
unlink($this->getTempPath() ?? '');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
unlink($this->getTempPath() ?? '');
unlink($this->getTempPath());

If the file exists, it can't be null. I suspect you copied this from __destruct() but for context, the null coalescing operator there was added by a naive automated approach to PHP 8.1 compatibility. We don't need or want to add unnecessary null coalescing operators in manual changes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requested change made, and PR retargeted to 1.13

The vips intervetion image backend isn't working right now, because InterventionBackend unlinks the temporary file too early. It is removed before the actual libvips commands are run against it, which makes them fail. The temporary file is removed in the destructor of InterventionBackend anyway, so this section is unnecessary.
Remove the temporary file in Intervention image backend when resetting the image resource.
Copy link
Member

@GuySartorelli GuySartorelli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, looks good.

@GuySartorelli GuySartorelli merged commit 8597eae into silverstripe:1.13 Aug 7, 2023
9 checks passed
@GuySartorelli
Copy link
Member

This will be automatically tagged as 1.13.5 once CI has finished running on it

@lerni
Copy link

lerni commented Aug 21, 2023

I was excited when I saw this got merged. Especially since AVIF 'll be available in Edge 117, which 'll make it broadly available soon. What I noticed is, that I still get [Emergency] Uncaught Jcupitt\Vips\Exception: libvips error: /var/www/html/silverstripe-cache/www-data/interventionimage_VO3qQo.jpg: unable to open for read unix error: No such file or directory when using libvips with jonom/focuspoint. Libvips also works with FP if I comment-out unlink in __descruct() but not otherwise.

@lerni
Copy link

lerni commented Feb 19, 2024

I've made an attempt to make focuspoint work with vips and came up with a suboptimal solution 😁 The problem is similar to this issue - the temporary file is unlinked after the first operation but focuspoint chains operations like $backend->resizeByWidth($width)->crop($cropOffset, 0, $width, $height). I would appreciate ideas on how this could be tackled other than just cloning.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants