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

Im7 Add SetImageMask #256

Merged
merged 2 commits into from
Apr 25, 2021
Merged

Im7 Add SetImageMask #256

merged 2 commits into from
Apr 25, 2021

Conversation

justinfx
Copy link
Member

Fixes #245

@justinfx justinfx changed the base branch from master to im-7 April 19, 2021 20:32
@justinfx
Copy link
Member Author

Refs eventual fix: ImageMagick/ImageMagick#3566

@justinfx
Copy link
Member Author

@pfitzner did this work for you?

@pfitzner
Copy link

pfitzner commented Apr 25, 2021 via email

@justinfx justinfx merged commit 5c47103 into im-7 Apr 25, 2021
@justinfx justinfx deleted the im7_SetImageMask branch April 25, 2021 03:44
@justinfx
Copy link
Member Author

@pfitzner, I would have thought it would work fine in module-mode via:

go get gopkg.in/gographics/imagick.v3/imagick@im7_SetImageMask

Anyways, I added a quick test just to make sure it doesn't crash, and merged it to the im7 branch (which is the main branch for v3).

Thanks for the general commentary on the Go language. I use Go in multiple production projects, but to be honest I only ended up becoming the maintainer of this project because at one point I was a user of it and no one else was maintaining it. So I just keep it going now and fix things for people when I have time.

@pfitzner
Copy link

pfitzner commented Apr 25, 2021 via email

@pfitzner
Copy link

pfitzner commented Apr 26, 2021 via email

@justinfx
Copy link
Member Author

@pfitzner I actually have no idea how MagickSetImageMask works, beyond what the ImageMagick C API actually documents.

https://imagemagick.org/api/magick-image.php#MagickSetImageMask

We usually just copy across the doc string from the C API. And in this case they don't seem to explain the PixelMask enum.

https://imagemagick.org/api/MagickCore/pixel_8h.html#a6e97344e98e8667f420da73ba326c25e

So I am not sure if you are calling out these Go bindings as being poorly documented, or ImageMagick. If it's the latter, then I agree it is insufficiently documented to easily know what that parameter controls. One might need to either Google for an example of using that api call, or ask for clarification on the ImageMagick forum?

@pfitzner
Copy link

pfitzner commented Apr 26, 2021 via email

@justinfx
Copy link
Member Author

Try here: https://github.com/ImageMagick/ImageMagick/discussions

Don't forget, this project is just a binding. So it's not meant to be authoritative on how to use the project it binds. We just expose ImageMagick through cgo and ensure that our layer doesn't have bugs or leaks. If it was not a binding, then I would expect it to adequately document everything.

@pfitzner
Copy link

pfitzner commented Jun 9, 2021 via email

@justinfx
Copy link
Member Author

justinfx commented Jun 9, 2021

@pfitzner unfortunately no I don't have a Mac M1 to test this against. I was only able to run your code on ImageMagick7 with Ubuntu 18.04. And as you said about other architectures, it didn't crash or show any kind of steady memory increase. What size images are you testing with? I tried between 3-7 MB images.

I recall Mac M1 arch being something that has newly been added as support to the Go tooling, so maybe there is some kind of bug if it only happens on this architecture?

You aren't using Goroutines in this example so it shouldn't be trying to share anything across threads. But for completeness you could try adding this at the top of your main? https://golang.org/pkg/runtime/#LockOSThread

func main() {
    runtime.LockOSThread()
    defer runtime.UnlockOSThread()

That forces the current goroutine to be locked to the current OS thread. Aside from that, you might want to consider posting this reproduction as a bug report for Go, or to the golang-nuts mailing list?

@pfitzner
Copy link

pfitzner commented Jun 9, 2021 via email

@justinfx
Copy link
Member Author

@pfitzner thats great to hear that my suggestion helped isolate the fix! I will watch for your thread to see if they identify it as a Mac M1 arch specific cgo bug

@pfitzner
Copy link

pfitzner commented Jun 12, 2021 via email

@justinfx
Copy link
Member Author

It looks like any call or sequence of calls into IM that might churn memory on the C side should be bracketed by a lock. Maybe even simpIe getters and setters. 🤯

As it's a known problem with Go and foreign code, these guardrails ought to go into the API surrounding the actual cgo call.

Seeing as the problem only cropped up under a specific architecture, we probably don't want to try and put too many fixes in place for general use. A documentation note is probably a good idea, to indicate when this situation can occur and what a recommended fix could be.
I don't think adding a LockOSThread around a single cgo call will fix this, seeing as the problem might occur in combination of acquiring and freeing C memory from ImageMagick? We wouldn't have api control over the lifetime to keep the acquisition and destruction within the same OS thread. However if it really does happen only within a single cgo call then maybe it could be fixed. But I interpreted your report as being about the entire lifetime. ImageMagick C API has its own specific calls to handle the memory, which we call into. And it could be possible they are relying on threadlocal storage.

In any case, a warning aught to be put into the docs recommending thread locking,

I agree. We could note that we have detected this problem in Mac M1 targets and offer an example of which scope one may want to add LockOSThread

Chalk another one up to Go's downside.

Snarky comments about Go are not necessary here. It's obviously an issue with cgo on a specific target. Cgo is not Go. It is just a mechanism to translate calls. Rust does not use an m:n scheduler like Go, which makes Rust calls map more directly to OS threads (amongst other calling convention differences) . There isn't a problem with Go here. Just the compatibility of a cgo compilation target.
Try to stay positive. It ensures others will want to offer help for free, even when the project they are helping someone with is not a project they initially created, or even use anymore 😉

@pfitzner
Copy link

pfitzner commented Jun 12, 2021 via email

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.

Masking images in v3
2 participants