and… Lion. (the further woes of mysql and mod_perl) (0 comments)

and… Lion. (the further woes of mysql and mod_perl)

Saturday, September 03, 2011 - 09:50 PM

I try to do my development on my personal machine, not the server. Once it's working, I move it to my development machine, fix bugs, move it to staging, fix bugs, move it live, panic.

Hopefully that panic is followed by things working, hopefully quickly, but I digress.

Step 1 is keeping things working on my own machines. I run Mac OS on all those machines, Debian Linux on the servers. It seems that every Mac upgrade causes its own set of headaches. This time, after upgrading to Lion, the problem was that (after all sorts of other, expected, upgrading annoyances) all my perl code ran as test scripts, but wouldn't run under mod_perl. I would see:

[Sat Sep 03 18:39:29 2011] [error] install_driver(mysql) failed: Can't load '/Users/phillip/Sites/hosting/perl/lib/perl5/darwin-thread-multi-2level/auto/DBD/mysql/mysql.bundle' for module DBD::mysql: dlopen(/Users/phillip/Sites/hosting/perl/lib/perl5/darwin-thread-multi-2level/auto/DBD/mysql/mysql.bundle,
1): Library not loaded: libmysqlclient.16.dylib
    Referenced from: /Users/phillip/Sites/hosting/perl/lib/perl5/darwin-thread-multi-2level/auto/DBD/mysql/mysql.bundle
    Reason: image not found at /System/Library/Perl/5.12/darwin-thread-multi-2level/ line 204.
    at (eval 3317) line 3
    Compilation failed in require at (eval 3317) line 3.
    Perhaps a required shared library or dll isn't installed where expected

It turns out that when you search for this kind of error, you get a lot of help for how to fix it under Rails. I don't want to steal from any of the numerous posts on how to fix it there, but it took reading through a whole bunch of those to figure out the "correct" solution, and I don't have a particular one to credit with helping me, although they all helped me grok the situation. It also would have been faster if I had known more about how Macs deal with dynamic libraries.

The important thing is that libraries contain within them the paths to the other libraries they work with. You can see these included paths with the "otool" command. In this case it was the perl DBD::mysql file mysql.bundle that was unable to find a library it needed. Specifically the libmysqlclient.16.dylib file: $ otool -L /Users/phillip/Sites/hosting/perl/lib/perl5/darwin-thread-multi-2level/auto/DBD/mysql/mysql.bundle
  libmysqlclient.16.dylib (compatibility version 16.0.0, current version 16.0.0)
  /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.0.0)

The problem file is the first returned "libmysqlclient.16.dylib" the "mysql.bundle" is looking for. It's looking relatively, and it needs to look or it more absolutely.

The tool to fix this is apparently "install_name_tool". You can use this to change those resulting lines that otool returned.

Now, the actual path of my "libmysqlclient.16.dylib" library is "/usr/local/mysql-5.5.9-osx10.6-x86_64/lib/libmysqlclient.16.dylib". However, I know that there's a "mysql" link corresponding to "mysql-5.5.9-osx10.6-x86_64" and another "libmysqlclient.dylib" corresponding to "libmysqlclient.16.dylib". So instead of using "/usr/local/mysql-5.5.9-osx10.6-x86_64/lib/libmysqlclient.16.dylib" I can use "/usr/local/mysql/lib/libmysqlclient.dylib". Hopefully future mysql upgrades will maintain those symlinks and I won't have to do this again.

The command I need to run, then, is to tell "mysql.bundle" where to find "libmysqlclient.dylib". This requires admin/sudo privileges so it is: $ sudo install_name_tool -change libmysqlclient.16.dylib /usr/local/mysql/lib/libmysqlclient.dylib /Users/phillip/Sites/hosting/perl/lib/perl5/darwin-thread-multi-2level/auto/DBD/mysql/mysql.bundle or, in more generic terms: $ sudo install_name_tool -change "old, bad library name" "new, fully functional path" "really long path to the problem child/library" After changing the relative path to an absolute one, otool says: $ otool -L /Users/phillip/Sites/hosting/perl/lib/perl5/darwin-thread-multi-2level/auto/DBD/mysql/mysql.bundle
  /usr/local/mysql/lib/libmysqlclient.dylib (compatibility version 16.0.0, current version 16.0.0)   /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.0.0)
and apache is starting happily.

actually, it found more …problems… but they were generic and more easily sorted out. End of the day, everything is happy now. On the computer, at least.

Postscript: the reason this wasn't an issue under my test scripts, run from my home account, is that my "DYLD_LIBRARY_PATH" environment variable contains "/usr/local/mysql/lib" as a path. Apache doesn't run under my account, and its security…stuff… makes it difficult to set a similar path that DBD::mysql will see.

Threshold:  Locked
The Fine Print: The above comments are owned by whoever posted them. We are not responsible for them in any way.
Hell, let's face it, we're not responsible for anything; including the things we say, do, or think. And if you sue us because you think we are? Well, we're not responsible for that either.