I’m sure some of you have experienced strange errors after upgrading PHP extensions, specifically in my case using FreeBSD’s ports. The errors would look something like this:

php: PHP Warning: PHP Startup: Unable to load dynamic library '/usr/local/lib/php/20060613/soap.so' - /usr/local/lib/php/20060613/soap.so: Undefined symbol "ps_globals" in Unknown on line 0
php: PHP Warning: PHP Startup: Unable to load dynamic library '/usr/local/lib/php/20060613/xsl.so' - /usr/local/lib/php/20060613/xsl.so: Undefined symbol "dom_node_class_entry" in Unknown on line 0

Obviously I’m having problems here with the SOAP and XSL PHP extensions, but this problem has manifested itself before with numerous other extensions, so these are just examples. My usual solution was to simply rebuild the extension(s) causing problems. This worked for me, and it will most likely also work for you, but not for the reason you might expect. The problem appears to be a case of “hey you linked me against an {older|invalid} shared library and now I can’t resolve all of my symbols” that you see when you build programs incrementally from source without ensuring consistency, or try to load modules into a Linux kernel that were built against a previous kernel release. Because I’ve seen similar issues before, I thought I was doing the right thing, but I was a little frustrated as it seemed that ports wasn’t doing its job. Realistically I wasn’t that far off.

When PHP parses extensions.ini, it doesn’t appear to do correct (or any?) checks on the modules for interdependency. While ideally all of the modules would be independent of one another, they aren’t. PDO, for example, is an extension all by itself, but its drivers are clearly dependent on the PDO extension. The reason rebuilding specific extensions works for me is that ports does something automagic (very clean, too) when building extensions: it checks extensions.ini for the module’s existence when it installs or deinstalls a specific module. It cleans up for you by removing the module’s entry when you deinstall the module, and it adds an entry when you install a module. This meant that when I went to install that specific module, ports placed the corresponding entry at the bottom of extensions.ini. I can still build extensions in any order I want (assuming we’re not building extensions with different ABIs/APIs) but if I load a module before I load its dependency, the module is going to complain about whatever it needs from its dependency at runtime.

I solved this problem by building a known good extensions.ini and placed it next to the real extensions.ini in the filesystem, and I simply copy it over when I rebuild extensions. I use the php.net documentation to initially discover dependencies, and add and remove them from my known good configuration as needed.

2 Responses to “PHP’s extensions.ini: order matters”

  1. Marcin Says:

    Hmmm… I’ve read above and make some changes in extensions.ini order and I can confirm: order matters. Now php works with all extesions enabled and even with one which was unloadable before :) No warnings. No core dumps. Thaks for an info :) Regards. Marcin K.

  2. Chazz Says:

    thanks for sharing


Leave a Reply