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

nokogiri 1.6.0 fails to load embedded version of libxml2 if absolute path changes #923

Merged
merged 8 commits into from
Oct 22, 2013

Conversation

knu
Copy link
Member

@knu knu commented Aug 17, 2013

Our build system does a bundle install --path ./bundler on one machine; then tars up the result and sends it to the rest of production.

Unfortunately the tar-ball gets extracted into a different directory on the production servers from the temporary build server directory, which means that the absolute path hard-coded into nokogiri.so at compile time is wrong. This means that nokogiri picks up the system version of libxml2 and not the embedded version and you get a warning on start-up.

I think this is fixable on Linux by using Dylib.dlopen to open the libxml2.so file eagerly; not certain the correct way to fix on a Mac.

To replicate see the instructions at https://github.com/ConradIrwin/nokogiri-test.

@envygeeks
Copy link

This might be related so I'm going to stick this here for now but if it's not then I'll move it to it's own ticket. We have a similar problem but in a way a bit opposite of his result. We package our production scripts and send them off and they too get untared into a different directory.

Instead of doing what @ConradIrwin states, for us, it claims that it was built against 2.8.0 of libxml2 and loaded 2.9.0 through dynamic linking, none of our dev or production servers contain libxml 2.8.0 and it was in-fact built against 2.9.0 but this was triggered by the paths changing and it being unpackaged into /srv instead of /home/user/development/user/project.

The message: Nokogiri was built against LibXML version 2.8.0, but has dynamically loaded 2.9.0

@ghost
Copy link

ghost commented Jun 22, 2013

This problem also makes it difficult to build packages for nokogiri, as I used to do here.

@sage-andrew-taylor
Copy link

I'm seeing this problem, and I agree it's an issue. Have we any expectation that this will be fixed ? I've just mailed the mailing list. I would expect that libxml2_path would refer to the relative ./vendor/bundle path at the time of execution not the ./vendor/bundle path at the time it was built.

https://gist.github.com/sage-andrew-taylor/cbdd3c6852e2490e5e00

Thanks

andrew

@hone
Copy link

hone commented Aug 2, 2013

We're running into this issue on Heroku as well. Our build environment is different than our runtime, which is spewing this error.

@knu
Copy link
Member

knu commented Aug 3, 2013

I guess we should link the bundled libraries statically. Since they are only used by nokogiri.so, there is no benefit we can get from dynamic linking. Static linking allows us to remove the stuff "ports" have installed after successfully building the extension as a bonus.

@hone
Copy link

hone commented Aug 3, 2013

+1 on static linking.

@Peeja
Copy link

Peeja commented Aug 7, 2013

Hello. This is a message for people following the URL in the message shown by the new version of the Heroku Ruby buildpack, as of heroku/heroku-buildpack-ruby#124.

Since that landed, I've been unable to deploy because my slug build times went over 15 minutes. Turns out this is because the new version of the buildpack clears the Bundler cache to get rid of any old builds of Nokogiri. If you have enough dependencies, that slows things down enough to time out a slug build.

Fortunately I've solved the problem. If you've run into this problem then your cache has already been cleared, so the buildpack no longer needs to clear it for you. I adjusted the buildpack on a branch to skip clearing the cache. First, point to the tweaked buildpack:

$ heroku config:set [-a app-name] BUILDPACK_URL=https://github.com/nerdfighteria/heroku-buildpack-ruby.git#nokogiri-busted-cache-fix

Then push to deploy as normal. It's possible you'll need to try to deploy more than once: each time you'll get through re-caching more gems. (That would mean you have a whole lot of dependencies, though.)

Once you've deployed, you can switch back to the main-line buildpack. In the future, it will see that you've built with a newer version of the buildpack and that you therefore don't need your cache cleared.

$ heroku config:unset [-a app-name] BUILDPACK_URL

Hope that's helpful to someone!

@ghost ghost assigned knu Aug 8, 2013
@knu
Copy link
Member

knu commented Aug 8, 2013

I'm currently working on static linking.

@knu
Copy link
Member

knu commented Aug 8, 2013

I've just pushed my commits to the static_clean branch which makes nokogiri statically link the packaged libraries by default.

Would you guys give it a try? Run rake install_gem and see what ldd "$(gem which nokogiri/nokogiri.so)" gives.

@flavorjones Could you review my changes? The branch also includes a patch that cleans files generated by ports that are unnecessary to run nokogiri, which will hopefully eliminate recent complaints on how nokogiri installation is bloated.

knu added 3 commits August 12, 2013 17:41
…ions.

Now that we use packaged libraries by default, Nokogiri should build
for most usrs without bothering system libraries.

We have the options --with-{xml2,xslt,exslt}-{dir,include,lib}=dir
supported and also consult pkg-config(1) for libxml2, libxslt and
libexslt.  What else should you want?
A new option --disable-static allows user to link packaged libraries
dynaminally.

Fix priority problems with include directories and library directories
by manipulating $CPPFLAGS, $LIBPATH and $libs correctly.
@knu
Copy link
Member

knu commented Aug 21, 2013

@flavorjones What do you think about the changes?

@hone
Copy link

hone commented Sep 20, 2013

@flavorjones bump from gogaruco :)

@larskanis
Copy link
Member

@knu: I did some testing of your static_clean branch on Ubuntu-13.10. After rake gem I used something like env MAKE="make -j2 V=1" gem inst -l pkg/nokogiri-1.6.0.gem --verbose -- --disable-clean to install the gem. Beside the issue above, everything worked.

When installed with --disable-static I get the following shared object:

$ ldd `gem which nokogiri/nokogiri.so `
        linux-vdso.so.1 =>  (0x00007fffb53fe000)
        libruby.so.2.0 => /home/lars/.rvm/rubies/ruby-2.0.0-p247/lib/libruby.so.2.0 (0x00007f4d12ff0000)
        libexslt.so.0 => /home/lars/.rvm/gems/ruby-2.0.0-p247/gems/nokogiri-1.6.0/ports/x86_64-linux-gnu/libxslt/1.1.28/lib/libexslt.so.0 (0x00007f4d12ddb000)
        libxslt.so.1 => /home/lars/.rvm/gems/ruby-2.0.0-p247/gems/nokogiri-1.6.0/ports/x86_64-linux-gnu/libxslt/1.1.28/lib/libxslt.so.1 (0x00007f4d12b9c000)
        libxml2.so.2 => /home/lars/.rvm/gems/ruby-2.0.0-p247/gems/nokogiri-1.6.0/ports/x86_64-linux-gnu/libxml2/2.8.0/lib/libxml2.so.2 (0x00007f4d1283d000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4d1243c000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f4d1221f000)
        librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f4d12017000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f4d11e12000)
        libcrypt.so.1 => /lib/x86_64-linux-gnu/libcrypt.so.1 (0x00007f4d11bd9000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f4d118d5000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f4d1369e000)
        libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f4d116bb000)
        liblzma.so.5 => /lib/x86_64-linux-gnu/liblzma.so.5 (0x00007f4d11499000)

When installed with default params it results in the following shared object:

$ ldd `gem which nokogiri/nokogiri.so `
        linux-vdso.so.1 =>  (0x00007fff62389000)
        libruby.so.1.9 => /home/lars/.rvm/rubies/ruby-1.9.3-p448/lib/libruby.so.1.9 (0x00007f36128aa000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f361256c000)
        libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f3612353000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f3612136000)
        librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f3611f2d000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3611b66000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f3611962000)
        libcrypt.so.1 => /lib/x86_64-linux-gnu/libcrypt.so.1 (0x00007f3611728000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f361313e000)

I wonder about the missing reference to liblzma although configure.log of libxml2 has

Checking lzma
checking lzma.h usability... yes
checking lzma.h presence... yes
checking for lzma.h... yes
checking for lzma_code in -llzma... yes

Both variants are usable to run ruby -Ilib:test test/test_reader.rb successfully.

Beside that I'm not sure if extconf.rb lines 244-258 are really necessary, but I didn't do any tests to that. Line 272 is probably not very portable across compilers other than gcc.

By all means the clean step is a clever mechanism.

@knu
Copy link
Member

knu commented Oct 14, 2013

@larskanis Thanks for testing. Here's a couple of comments as a reponse.

  • As for portability, some kind of guard should indeed be added that checks if the compiler/linker flags are supported.
  • LZMA support is not used by Nokogiri, so it shouldn't be a problem as long as it builds and loads fine.

@knu
Copy link
Member

knu commented Oct 22, 2013

I'll merge this after making it an option to entirely remove the tmp directory, unless any objection is raised.

@knu knu merged commit f5ef8f8 into master Oct 22, 2013
@knu
Copy link
Member

knu commented Oct 22, 2013

I made it just remove the ports build directory by default.

@byrnejb
Copy link

byrnejb commented Nov 20, 2013

Where is this at? When will nokogiri go back to building with system libs?

gbenedict pushed a commit to RedFunnel/heroku-buildpack-ruby that referenced this pull request Jan 9, 2014
As of nokogiri 1.6.0, they default to using the vendored libxml2 libs.
This is problematic for two reasons. First, with the way the heroku
build environment works,
sparklemotion/nokogiri#923. This means it
won't link nokogiri.so properly since it's dependent on hardcoded paths
that don't exist during runtime. Second, compiling libxml2 and friends
is unnecessary since we have them already setup. We should skip this to
speed up deploys.
squeedee pushed a commit to cloudfoundry/ruby-buildpack that referenced this pull request Apr 10, 2014
As of nokogiri 1.6.0, they default to using the vendored libxml2 libs.
This is problematic for two reasons. First, with the way the heroku
build environment works,
sparklemotion/nokogiri#923. This means it
won't link nokogiri.so properly since it's dependent on hardcoded paths
that don't exist during runtime. Second, compiling libxml2 and friends
is unnecessary since we have them already setup. We should skip this to
speed up deploys.
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.

7 participants