-
Notifications
You must be signed in to change notification settings - Fork 60
undefined method 'new_from_file' for Vips::Image:Class #107
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
Comments
You mean sometimes it works, sometimes not? #98 sounds a little similar. That was (I think) to do with the way the vips gem handles startup. Maybe try adding something to trigger initialization earlier? You could try adding x = Vips::Image.black 1, 1 Just after the |
Thank John, yes looks a bit like #98. I will try your suggestion and report back. |
On another point, have you looked at the http://jcupitt.github.io/libvips/API/current/libvips-resample.html#vips-thumbnail |
For example, shrink a 9400 x 9400 pixel jpg down to 94 pixels across:
|
great, will update to that! BTW I moved the require in the method close to where the class is used and it does seem to stop the errors (https://github.com/tomasc/dragonfly_libvips/blob/master/lib/dragonfly_libvips/processors/thumb.rb#L23) – but let me give it more time before we close this |
BTW2 @jcupitt – this is a feature of 8.5.x vips, correct? If so, is there going to be updated OS X homebrew formula? (latest seem to be 8.4.5) |
Yes, there's an updated formula in the queue for approval, they've just not merged it yet: https://github.com/Homebrew/homebrew-science/pull/5399 The CI is failing, but I think that's not vips.rb's fault, it looks like pycairo is broken at the moment. |
I see, thank you! |
Is there a performance hit from having the require there? As long as vips is only loaded once, sure! Did you try initing vips on require (put some not-useful call to vips in just after the require)? |
I believe subsequent calls to |
BTW3 that speed gain of |
... the way vips init works, not much happens when the require runs, it just loads the typelib and adds some hooks. The first time you try to access a vips constant or method, the introspection fires and the rest of the binding is built. You can see the logic here: https://github.com/jcupitt/ruby-vips/blob/master/lib/vips.rb#L44 So ... if you require, then freeze the ruby process, then fork() for each request (at least rails does this, don't know about dragonfly) you will trigger the init as part of each request process, and perhaps have terrible confusion and breakage. If you init after require, vips will be loaded up and ready to go when the request comes in, and can never be run from more than one context. |
The JPG gives a very nice speedup, and it's probably the most common case, so that's great. |
when I do require 'vips'
Vips::Image.black 1, 1 at the top of the file I get
|
speed up on PDF resize will be very welcomed! |
Oh, weird, I wonder why that is. I guess if you make a file called x.rb:
Then:
works OK? |
it does … |
Could you try this in dragonfly: require 'vips'
Vips::set_debug TRUE
Vips::Image.black 1,1 It'll make the gem output some logging stuff as it starts up. You should see the missing const triggering |
yes:
|
Ah OK, so it's initing correctly, but then I think forking before each request, so the child is not inited. You're right, move the require to just before the first use. You'll be starting up vips for each request, but perhaps that's unavoidable :( It only adds 20ms or so, so perhaps it's not too bad. |
Hmm … too bad. |
@jcupitt sadly I am still seeing the same errors in production even after moving the require inside of the method. I will try to see if I can track the issue down, but have to admit I have not many ideas where to look … Maybe we will need to switch back to perusing the command line vipsthumbnail for the time being. |
Hi again, I had an idea last night. I wonder if Ruby could be unloading the libvips binary somehow, perhaps on GC? This looks a little like a problem we had in the php binding: So the fix might be to add an extra library load during init to prevent unload. Is there a simple way for me to run dragonfly in a harness here? If not, could you copy-paste some more of your log? We need to see how much of ruby-vips init is repeated the second time it loads, and verify that it is trying to reinit within the same process. Could you print the pid just before
So we see this first time:
What is the output the second time through when it fails? @felixbuenemann, this possibly sounds like your bug too, do you know if Ruby can unload libraries on GC? |
thanks for this @jcupitt, I will plug this in and get back to you with logs |
@jcupitt I think the It's at the end of the output of the debug:
|
Oh, maybe |
The |
Oh I see, sorry. I guess change vips to log to a file instead. You just need to change the log method: https://github.com/jcupitt/ruby-vips/blob/master/lib/vips.rb#L8 You're a better Ruby programmer than me, but I guess open |
The encoding error means that the debug print is trying to write binary data to stdout, which is opened with utf-8 encoding and the conversion fails. The ruby docs for the Encoding Class contain an explanation of ruby's internal and external encoding. |
@tomasc can we close this? |
@jcupitt this is till happening – quite often actually in both my websites using ruby-vips. I owe you debug log, will try to get it soon. |
Hello again, could you try deleting this code from vips.rb: https://github.com/jcupitt/ruby-vips/blob/master/lib/vips.rb#L142 It might be causing confusion with fork and Ruby, I read somewhere, and it's not really necessary. |
Thanks! |
I've almost got a new version of the gem working: https://github.com/jcupitt/ruby-vips/tree/ffi-experiment It's 2.0.0, based on ffi instead of gobject-introspection, so all these problems might go away. It fails 47 of 50 tests right now, but it does seem to sort-of work. Hopefully it'll be ready for testing by the end of today. |
whoa, impressive @jcupitt ! |
@tomasc I don't think removing the q=Queue.new
Thread.new { require "vips"; r = Vips::Access::SEQUENTIAL rescue $!; q << r }
Thread.new { require "vips"; r = Vips::Image.new_from_array([0]) rescue $!; q << r }
q.pop
=> #<NoMethodError: undefined method `new_from_array' for Vips::Image:Class
q.pop
=> #<Vips::Access sequential> |
@felixbuenemann yes I am on puma, I tried |
The |
I see, will try. |
It might be as easy as taking a mutex around initialization. Should definitely be fixable in ruby-vips. |
way beyond my knowledge of Ruby :-) |
The following code works without error: s=Mutex.new
q=Queue.new
Thread.new { require "vips"; r = s.synchronize { Vips::Access::SEQUENTIAL rescue $! }; q << r }
Thread.new { require "vips"; r = s.synchronize { Vips::Image.new_from_array([0]) rescue $! }; q << r }
q.pop
=> #<Vips::Image:0x7f8b30caaf68 ptr=0x7f8b2f5c2000>
q.pop
=> #<Vips::Access sequential> Of course this is not the actual solution, is only shows that synchronizing the init helps. |
Here's a runnable test case for the bug: require "vips"
10.times do
fork do
q=Queue.new
th=[]
th << Thread.new { q << (Vips::Access::SEQUENTIAL rescue $!) }
th << Thread.new { q << (Vips::Image.new_from_array([0]) rescue $!) }
th.map(&:join)
puts q.pop.inspect
puts q.pop.inspect
end
end
Process.waitall Note that the The different exceptions I get are:
This test case is very similar to what happens in puma cluster mode:
@jcupitt I'll try to come up with a fix unless you beat me to it ;-) |
Wow yes, vips init certainly does not try to be threadsafe, this certainly needs fixing. @felixbuenemann please go ahead. The experimental ffi ruby-vips 2.0 has the same top bits as ruby-vips, just a new backend, so your fix should copy over very simply. |
The experimental new ruby-vips passes the test suite: #115 Testing very welcome! |
@tomasc The bug from this issue should be fixed in ruby-vips 1.0.6. |
I am getting errors such as
undefined method 'new_from_file' for Vips::Image:Class
oruninitialized constant Vips::Image
from here, seemingly randomly:https://github.com/tomasc/dragonfly_libvips/blob/master/lib/dragonfly_libvips/processors/thumb.rb#L24
vips
is required, I have vips-8.5.2 installed (Ubuntu 14), withgobject-introspection (3.1.1)
,ruby-vips (1.0.4)
Can't seem to track down the source of the issue … any ideas please?
Thanks,
Tomas
The text was updated successfully, but these errors were encountered: