php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #24582 Extensions cannot be loaded dynamically on Solaris / iPlanet
Submitted: 2003-07-10 04:53 UTC Modified: 2004-03-15 10:59 UTC
From: CVKEWCZBUTBW at spammotel dot com Assigned:
Status: Closed Package: Scripting Engine problem
PHP Version: 5CVS, 4CVS OS: Solaris
Private report: No CVE-ID:
 [2003-07-10 04:53 UTC] CVKEWCZBUTBW at spammotel dot com
Description:
------------
I attempt to load a PHP extension (namely, the Java extension) dynamically in a Solaris / iPlanet environment.

Actual result:
--------------
I get this log message:

[08-Jul-2003 16:19:08] PHP Warning:  Unable to load dynamic library '/usr/local/php-4.2.1_gd_java/lib/php/extensions/no-debug-zts-20020429/java.so' - ld.so.1: ns-httpd: fatal: relocation error: file /usr/local/php-4.2.1_gd_java/lib/php/extensions/no-debug-zts-20020429/java.so: symbol core_globals_id: referenced symbol not found in Unknown on line 0

This is reproducible on PHP 4.2.1 and on PHP 4.3.2.

The reason for this problem is as follows:
------------------------------------------

The web server loads the PHP module through "dlopen()". iPlanet, obviously opposed to Apache, does not set the RTLD_GLOBAL option when calling "dlopen()", which means that the PHP core symbols are not published. Consequently, when PHP loads an extension with "dlopen()", then that extension does not see the PHP core symbols (the first of which is "core_globals_id"). iPlanet obviously has no option to set the RTLD_GLOBAL flag when loading the PHP module.

One solution is as follows:
---------------------------

An extension can "see" the PHP core symbols if PHP sets the "RTLD_PARENT" option when loading the extension. The patch required to achieve this is:

*** Zend/zend.h.orig    Wed Jul  9 17:25:37 2003
--- Zend/zend.h Wed Jul  9 17:43:32 2003
***************
*** 73,79 ****
  #  define RTLD_GLOBAL 0
  # endif
 
! # define DL_LOAD(libname)                     dlopen(libname, RTLD_LAZY | RTLD_GLOBAL)
  # define DL_UNLOAD                                    dlclose
  # if DLSYM_NEEDS_UNDERSCORE
  #  define DL_FETCH_SYMBOL(h,s)                dlsym((h), "_" ## s)
--- 73,80 ----
  #  define RTLD_GLOBAL 0
  # endif
 
! /* AU 2003-07-09 */
! # define DL_LOAD(libname)                     dlopen(libname, RTLD_LAZY | RTLD_GLOBAL      |RTLD_PARENT|RTLD_GROUP|RTLD_WORLD)
  # define DL_UNLOAD                                    dlclose
  # if DLSYM_NEEDS_UNDERSCORE
  #  define DL_FETCH_SYMBOL(h,s)                dlsym((h), "_" ## s)


In other words: The "RTLD_PARENT|RTLD_GROUP|RTLD_WORLD" options must be added to the "dlopen()" call.

This patch was tested with PHP 4.2.1. The buggy line of code exists in all of versions 4.2.1, 4.3.2 and 5.0.0 beta, so I strongly presume that the problem exists in all PHP versions and that the fix also works for all PHP versions.

I have no clue if the code change I made is suitable for other environments and cofigurations. This requires regression testing on other platforms, which I cannot do. I believe someone from the PHP team should make a decision here.


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2003-07-10 10:46 UTC] sniper@php.net
RTLD_GROUP, RTLD_WORLD and RTLD_PARENT are not available
on Linux. (at least not defined at all in my system).

Also, according to Solaris man page for dlopen(), 
(if I read it correctly :), RTLD_GROUP and RTLD_WORLD are on by default anyway. So only option needed is RTLD_PARENT.

Could you try that only?

 [2003-07-10 10:50 UTC] sniper@php.net
We could also add those 3 extra ones always though if they just are defined..:)

 [2003-07-11 03:54 UTC] CVKEWCZBUTBW at spammotel dot com
> Also, according to Solaris man page for dlopen(),
> (if I read it correctly :), RTLD_GROUP and RTLD_WORLD
> are on by default anyway. So only option needed is
> RTLD_PARENT.
> Could you try that only?

The man page is not really clear about that. I understand that if you set NONE of the three flags, then "GROUP|WORLD" takes effect. So if you want all three flags, you have to specify "GROUP|WORLD|PARENT".

I have no easy way to try it. I'd propose:

#if defined(RTLD_GROUP) && defined(RTLD_WORLD) && defined(RTLD_PARENT)
#define DL_LOAD(libname) dlopen(libname, RTLD_LAZY | RTLD_GLOBAL | RTLD_GROUP | RTLD_WORLD | RTLD_PARENT)
#else
#define DL_LOAD(libname) dlopen(libname, RTLD_LAZY | RTLD_GLOBAL)
#endif
 [2003-07-24 15:10 UTC] sniper@php.net
Does the patch you provided fix the bug for you or not?
(I have no solaris access to test it with..)

 [2003-07-31 14:07 UTC] CVKEWCZBUTBW at spammotel dot com
Yes, the patch I provided in my July 10 posting fixes the bug for Solaris.
My July 11 posting proposes a modified patch which is more portable, esp. it does not break compilation in a Linux environment.
 [2004-03-15 10:59 UTC] sniper@php.net
This bug has been fixed in CVS.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.


 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Sat Apr 19 04:01:55 2014 UTC