rowland/fb

undefined symbol: isc_attach_database

plainlystated opened this issue · 7 comments

Excited to find this gem, but I'm having trouble getting it to run. I installed version 0.7.4 via 'gem install fb', and it built the native extension without a problem.

When I try to run the README, though, it complains:

$ ruby README 
ruby: symbol lookup error: /home/patrick/.rvm/gems/ruby-2.2.1@fb/gems/fb-0.7.4/fb.so: undefined symbol: isc_attach_database

I think I have the required client installed:

$ ls /usr/lib/libfb*
/usr/lib/libfbclient.so  /usr/lib/libfbclient.so.1  /usr/lib/libfbclient.so.1.5.6  /usr/lib/libfbembed.so  /usr/lib/libfbembed.so.1  /usr/lib/libfbembed.so.1.5.6

... but perhaps not...

I tried building from source and I see this when running extconf.rb:

$ ruby extconf.rb
checking for isc_attach_database() in -lfbclient... no
checking for isc_attach_database() in -lgds... no
creating Makefile

I'm running 2.2.1 in RVM.

Any help would be greatly appreciated. This library will be a huge help to me :)

I should also mention that I'm on ubuntu 14.04 and I installed firebird 1.5.6 from source to /opt/firebird. I tried using --with-opt-dir=/opt/firebird on extconf.rb but that didn't seem to have an effect.

I would try something like

strace ruby -e "require 'fb'" 2>&1 | less

and see which libraries it is trying to load. Search for "libfb" of course. I get

open("/usr/local/rbenv/versions/2.2.3/lib/libfbclient.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/local/rbenv/versions/2.2.3/lib/libfbclient.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 7
fstat(7, {st_mode=S_IFREG|0644, st_size=53484, ...}) = 0
mmap(NULL, 53484, PROT_READ, MAP_PRIVATE, 7, 0) = 0x7fcffa5c3000
close(7)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/usr/lib/libfbclient.so.2", O_RDONLY|O_CLOEXEC) = 7

Since you installed Firebird from source, make sure the libraries are properly registered:

strings /etc/ld.so.cache | grep libfb

I'm also on Ubuntu 14.04, but I use rbenv. Ruby 2.2.1 didn't want to install, but 2.1.8 and 2.2.3 both work for me. I haven't used Firebird < 2.x for several years, but I've heard reports of others still using it.

Yeah, the 1.5.6 requirement is to match a vendor's choice. I tried opening the files with 2.x and firebird said the files were invalid, so I guess when they did a major version bump they said 'screw it' to opening their pre 2.x files :(

It looks like I have the libs installed correctly. At least, I see them here:

$ strings /etc/ld.so.cache | grep libfb
libfbembed.so.1
/usr/lib/libfbembed.so.1
libfbembed.so
/usr/lib/libfbembed.so
libfbclient.so.2
/usr/lib/x86_64-linux-gnu/libfbclient.so.2
libfbclient.so.1
/usr/lib/libfbclient.so.1
libfbclient.so
/usr/lib/libfbclient.so

I don't see libfb mentioned anywhere in strace, though:

$ strace ruby -e "require 'fb'" 2>&1 | grep libfb
(no output)

Here's the libs it does try to load:

$ strace ruby -e "require 'fb'" 2>&1 | grep -oE "[a-z_0-9]+\.so" | sort | uniq
date_core.so
encdb.so
fb.so
ld.so
libcrypt.so
libc.so
libdl.so
libm.so
libpthread.so
libruby.so
operating_system.so
ruby.so
thread.so
transdb.so

FWIW, ldd doesn't mention it either:

$ ldd /home/patrick/.rvm/gems/ruby-2.2.1@fb/gems/fb-0.7.4/fb.so
        linux-vdso.so.1 =>  (0x00007ffe5aad8000)
        libruby.so.2.2 => /home/patrick/.rvm/rubies/ruby-2.2.1/lib/libruby.so.2.2 (0x00007fe46190f000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe46154a000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fe46132c000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fe461128000)
        libcrypt.so.1 => /lib/x86_64-linux-gnu/libcrypt.so.1 (0x00007fe460eef000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fe460be9000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fe461ffb000)

And, when I run the extconf.rb myself, this line returns nil, which I'm guessing means ruby can't find the library for some reason:

libs.find {|lib| have_library(lib, test_func) }

I'm not very familiar with native extensions in ruby. Is there some flag or somesuch I should be specifying?

Thanks for having a look and trying to help. This will be a huge help to me if I can get it to work.

At one time, extconf.rb would abort when have_library failed, but on some platforms, notably Darwin, the have_library function would fail even though the framework was available. So, now it crosses its fingers and violates the fail-early principle.

I'm not sure how your fb.so managed to build without finding fbclient.

brent@andromeda:~/src$ ldd /usr/local/rbenv/versions/2.1.8/lib/ruby/gems/2.1.0/gems/fb-0.7.4/fb.so
    linux-vdso.so.1 =>  (0x00007ffccdb65000)
    libfbclient.so.2 => /usr/lib/libfbclient.so.2 (0x00007fc17b20c000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc17ae47000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fc17ab41000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fc17a93d000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fc17a71f000)
    /lib64/ld-linux-x86-64.so.2 (0x00007fc17b701000)

To open a Firebird 1.5 database in 2.x, one would need to back it up with the -t (transportable) option using Firebird 1.5 and then restore it with 2.x. I don't know if it will work in reverse, though. Maybe if you don't use any 2.x-specific features?

One more explanation comes to mind: The output of your ldd command shows you're using a 64-bit Ruby. Firebird didn't support 64-bit until 2.0. The wire protocol is architecture-agnostic, but your libfbclient has got to be 32-bit, which would explain why it's not getting linked into your 64-bit program.

So, you either need to use a 32-bit Ruby or at least connect to your 32-bit server using a 64-bit, Firebird 2.x client.

As usual, if it breaks, you get to keep the pieces...

Were you able to resolve your 32/64-bit issues?

Unfortunately, not yet.

I've been shaving yaks trying to build a 32 bit ruby. Doesn't seem to work in RVM, even on a 32-bit OS (in a VM). Ugh.

Hoping to get more time this week to put into researching this.

I did kinda end up getting it to work, but I had to completely destroy the 64-bit build environment by one-by-one replacing packages with their 32-bit equivalent. Debian's multiarch stuff is a huge pain :(

I've decided to scrap that strategy, and will be doing what you mentioned above: export it on a 1.5.6 box and then run 2.x on my app boxes. I only need read-only access, so this strategy should work for me.

Thanks for the help!