summaryrefslogtreecommitdiff
path: root/ext/DynaLoader
diff options
context:
space:
mode:
Diffstat (limited to 'ext/DynaLoader')
-rw-r--r--ext/DynaLoader/DynaLoader_pm.PL41
-rw-r--r--ext/DynaLoader/Makefile.PL1
-rw-r--r--ext/DynaLoader/dl_aix.xs51
-rw-r--r--ext/DynaLoader/dl_dlopen.xs39
-rw-r--r--ext/DynaLoader/dlutils.c29
-rw-r--r--ext/DynaLoader/hints/aix.pl4
6 files changed, 147 insertions, 18 deletions
diff --git a/ext/DynaLoader/DynaLoader_pm.PL b/ext/DynaLoader/DynaLoader_pm.PL
index 8341b36130..0e0f79263d 100644
--- a/ext/DynaLoader/DynaLoader_pm.PL
+++ b/ext/DynaLoader/DynaLoader_pm.PL
@@ -28,7 +28,7 @@ package DynaLoader;
#
# Tim.Bunce@ig.co.uk, August 1994
-$VERSION = "1.03"; # avoid typo warning
+$VERSION = "1.04"; # avoid typo warning
require AutoLoader;
*AUTOLOAD = \&AutoLoader::AUTOLOAD;
@@ -411,7 +411,7 @@ sub dl_find_symbol_anywhere
DynaLoader - Dynamically load C libraries into Perl code
-dl_error(), dl_findfile(), dl_expandspec(), dl_load_file(), dl_find_symbol(), dl_find_symbol_anywhere(), dl_undef_symbols(), dl_install_xsub(), dl_load_flags(), bootstrap() - routines used by DynaLoader modules
+dl_error(), dl_findfile(), dl_expandspec(), dl_load_file(), dl_unload_file(), dl_find_symbol(), dl_find_symbol_anywhere(), dl_undef_symbols(), dl_install_xsub(), dl_load_flags(), bootstrap() - routines used by DynaLoader modules
=head1 SYNOPSIS
@@ -463,6 +463,7 @@ DynaLoader Interface Summary
$symref = dl_find_symbol_anywhere($symbol) Perl
$libref = dl_load_file($filename, $flags) C
+ $status = dl_unload_file($libref) C
$symref = dl_find_symbol($libref, $symbol) C
@symbols = dl_undef_symbols() C
dl_install_xsub($name, $symref [, $filename]) C
@@ -640,6 +641,42 @@ current values of @dl_require_symbols and @dl_resolve_using if required.
Linux, and is a common choice when providing a "wrapper" on other
mechanisms as is done in the OS/2 port.)
+=item dl_unload_file()
+
+Syntax:
+
+ $status = dl_unload_file($libref)
+
+Dynamically unload $libref, which must be an opaque 'library reference' as
+returned from dl_load_file. Returns one on success and zero on failure.
+
+This function is optional and may not necessarily be provided on all platforms.
+If it is defined, it is called automatically when the interpreter exits for
+every shared object or library loaded by DynaLoader::bootstrap. All such
+library references are stored in @dl_librefs by DynaLoader::Bootstrap as it
+loads the libraries. The files are unloaded in last-in, first-out order.
+
+This unloading is usually necessary when embedding a shared-object perl (e.g.
+one configured with -Duseshrplib) within a larger application, and the perl
+interpreter is created and destroyed several times within the lifetime of the
+application. In this case it is possible that the system dynamic linker will
+unload and then subsequently reload the shared libperl without relocating any
+references to it from any files DynaLoaded by the previous incarnation of the
+interpreter. As a result, any shared objects opened by DynaLoader may point to
+a now invalid 'ghost' of the libperl shared object, causing apparently random
+memory corruption and crashes. This behaviour is most commonly seen when using
+Apache and mod_perl built with the APXS mechanism.
+
+ SunOS: dlclose($libref)
+ HP-UX: ???
+ Linux: ???
+ NeXT: ???
+ VMS: ???
+
+(The dlclose() function is also used by Solaris and some versions of
+Linux, and is a common choice when providing a "wrapper" on other
+mechanisms as is done in the OS/2 port.)
+
=item dl_loadflags()
Syntax:
diff --git a/ext/DynaLoader/Makefile.PL b/ext/DynaLoader/Makefile.PL
index bcd45ae757..83cbd770b0 100644
--- a/ext/DynaLoader/Makefile.PL
+++ b/ext/DynaLoader/Makefile.PL
@@ -12,6 +12,7 @@ WriteMakefile(
'XSLoader_pm.PL'=>'XSLoader.pm'},
PM => {'DynaLoader.pm' => '$(INST_LIBDIR)/DynaLoader.pm',
'XSLoader.pm' => '$(INST_LIBDIR)/XSLoader.pm'},
+ depend => {'DynaLoader.o' => 'dlutils.c'},
clean => {FILES => 'DynaLoader.c DynaLoader.xs DynaLoader.pm ' .
'XSLoader.pm'},
);
diff --git a/ext/DynaLoader/dl_aix.xs b/ext/DynaLoader/dl_aix.xs
index f845681ae1..35242ed652 100644
--- a/ext/DynaLoader/dl_aix.xs
+++ b/ext/DynaLoader/dl_aix.xs
@@ -20,6 +20,15 @@
#include "perl.h"
#include "XSUB.h"
+/* When building as a 64-bit binary on AIX, define this to get the
+ * correct structure definitions. Also determines the field-name
+ * macros and gates some logic in readEntries(). -- Steven N. Hirsch
+ * <hirschs@btv.ibm.com> */
+#ifdef USE_64_BIT_ALL
+# define __XCOFF64__
+# define __XCOFF32__
+#endif
+
#include <stdio.h>
#include <errno.h>
#include <string.h>
@@ -29,15 +38,33 @@
#include <a.out.h>
#include <ldfcn.h>
+#ifdef USE_64_BIT_ALL
+# define AIX_SCNHDR SCNHDR_64
+# define AIX_LDHDR LDHDR_64
+# define AIX_LDSYM LDSYM_64
+# define AIX_LDHDRSZ LDHDRSZ_64
+#else
+# define AIX_SCNHDR SCNHDR
+# define AIX_LDHDR LDHDR
+# define AIX_LDSYM LDSYM
+# define AIX_LDHDRSZ LDHDRSZ
+#endif
+
/* When using Perl extensions written in C++ the longer versions
* of load() and unload() from libC and libC_r need to be used,
* otherwise statics in the extensions won't get initialized right.
* -- Stephanie Beals <bealzy@us.ibm.com> */
+
+/* Older AIX C compilers cannot deal with C++ double-slash comments in
+ the ibmcxx and/or xlC includes. Since we only need a single file,
+ be more fine-grained about what's included <hirschs@btv.ibm.com> */
#ifdef USE_libC /* The define comes, when it comes, from hints/aix.pl. */
# define LOAD loadAndInit
# define UNLOAD terminateAndUnload
-# ifdef USE_load_h
-# include <load.h>
+# if defined(USE_xlC_load_h)
+# include "/usr/lpp/xlC/include/load.h"
+# elif defined(USE_ibmcxx_load_h)
+# include "/usr/ibmcxx/include/load.h"
# endif
#else
# define LOAD load
@@ -394,10 +421,10 @@ static int readExports(ModulePtr mp)
{
dTHX;
LDFILE *ldp = NULL;
- SCNHDR sh;
- LDHDR *lhp;
+ AIX_SCNHDR sh;
+ AIX_LDHDR *lhp;
char *ldbuf;
- LDSYM *ls;
+ AIX_LDSYM *ls;
int i;
ExportPtr ep;
@@ -463,7 +490,11 @@ static int readExports(ModulePtr mp)
return -1;
}
}
+#ifdef USE_64_BIT_ALL
+ if (TYPE(ldp) != U803XTOCMAGIC) {
+#else
if (TYPE(ldp) != U802TOCMAGIC) {
+#endif
errvalid++;
strcpy(errbuf, "readExports: bad magic");
while(ldclose(ldp) == FAILURE)
@@ -511,8 +542,8 @@ static int readExports(ModulePtr mp)
;
return -1;
}
- lhp = (LDHDR *)ldbuf;
- ls = (LDSYM *)(ldbuf+LDHDRSZ);
+ lhp = (AIX_LDHDR *)ldbuf;
+ ls = (AIX_LDSYM *)(ldbuf+AIX_LDHDRSZ);
/*
* Count the number of exports to include in our export table.
*/
@@ -536,15 +567,19 @@ static int readExports(ModulePtr mp)
* the entry point we got from load.
*/
ep = mp->exports;
- ls = (LDSYM *)(ldbuf+LDHDRSZ);
+ ls = (AIX_LDSYM *)(ldbuf+AIX_LDHDRSZ);
for (i = lhp->l_nsyms; i; i--, ls++) {
char *symname;
if (!LDR_EXPORT(*ls))
continue;
+#ifndef USE_64_BIT_ALL
if (ls->l_zeroes == 0)
+#endif
symname = ls->l_offset+lhp->l_stoff+ldbuf;
+#ifndef USE_64_BIT_ALL
else
symname = ls->l_name;
+#endif
ep->name = savepv(symname);
ep->addr = (void *)((unsigned long)mp->entry + ls->l_value);
ep++;
diff --git a/ext/DynaLoader/dl_dlopen.xs b/ext/DynaLoader/dl_dlopen.xs
index 135f5112f2..8e4936d128 100644
--- a/ext/DynaLoader/dl_dlopen.xs
+++ b/ext/DynaLoader/dl_dlopen.xs
@@ -5,11 +5,13 @@
* Created: 10th July 1994
*
* Modified:
- * 15th July 1994 - Added code to explicitly save any error messages.
- * 3rd August 1994 - Upgraded to v3 spec.
- * 9th August 1994 - Changed to use IV
- * 10th August 1994 - Tim Bunce: Added RTLD_LAZY, switchable debugging,
- * basic FreeBSD support, removed ClearError
+ * 15th July 1994 - Added code to explicitly save any error messages.
+ * 3rd August 1994 - Upgraded to v3 spec.
+ * 9th August 1994 - Changed to use IV
+ * 10th August 1994 - Tim Bunce: Added RTLD_LAZY, switchable debugging,
+ * basic FreeBSD support, removed ClearError
+ * 29th Feburary 2000 - Alan Burlison: Added functionality to close dlopen'd
+ * files when the interpreter exits
*
*/
@@ -37,6 +39,17 @@
RTLD_LAZY (==2) on Solaris 2.
+ dlclose
+ -------
+ int
+ dlclose(handle)
+ void * handle;
+
+ This function takes the handle returned by a previous invocation of
+ dlopen and closes the associated dynamic object file. It returns zero
+ on success, and non-zero on failure.
+
+
dlsym
------
void *
@@ -57,7 +70,7 @@
Returns a null-terminated string which describes the last error
that occurred with either dlopen or dlsym. After each call to
dlerror the error message will be reset to a null pointer. The
- SaveError function is used to save the error as soo as it happens.
+ SaveError function is used to save the error as soon as it happens.
Return Types
@@ -180,6 +193,20 @@ dl_load_file(filename, flags=0)
sv_setiv( ST(0), PTR2IV(RETVAL));
}
+
+int
+dl_unload_file(libref)
+ void * libref
+ CODE:
+ DLDEBUG(1,PerlIO_printf(Perl_debug_log, "dl_unload_file(%lx):\n", libref));
+ RETVAL = (dlclose(libref) == 0 ? 1 : 0);
+ if (!RETVAL)
+ SaveError(aTHX_ "%s", dlerror()) ;
+ DLDEBUG(2,PerlIO_printf(Perl_debug_log, " retval = %d\n", RETVAL));
+ OUTPUT:
+ RETVAL
+
+
void *
dl_find_symbol(libhandle, symbolname)
void * libhandle
diff --git a/ext/DynaLoader/dlutils.c b/ext/DynaLoader/dlutils.c
index 664e331e7b..5c6bbea1ac 100644
--- a/ext/DynaLoader/dlutils.c
+++ b/ext/DynaLoader/dlutils.c
@@ -3,6 +3,9 @@
* Currently this file is simply #included into dl_*.xs/.c files.
* It should really be split into a dlutils.h and dlutils.c
*
+ * Modified:
+ * 29th Feburary 2000 - Alan Burlison: Added functionality to close dlopen'd
+ * files when the interpreter exits
*/
@@ -25,6 +28,31 @@ static int dl_debug = 0; /* value copied from $DynaLoader::dl_error */
#endif
+/* Close all dlopen'd files */
+static void
+dl_unload_all_files(pTHXo_ void *unused)
+{
+ CV *sub;
+ AV *dl_librefs;
+ SV *dl_libref;
+
+ if ((sub = get_cv("DynaLoader::dl_unload_file", FALSE)) != NULL) {
+ dl_librefs = get_av("DynaLoader::dl_librefs", FALSE);
+ while ((dl_libref = av_pop(dl_librefs)) != &PL_sv_undef) {
+ dSP;
+ ENTER;
+ SAVETMPS;
+ PUSHMARK(SP);
+ XPUSHs(sv_2mortal(dl_libref));
+ PUTBACK;
+ call_sv((SV*)sub, G_DISCARD | G_NODEBUG);
+ FREETMPS;
+ LEAVE;
+ }
+ }
+}
+
+
static void
dl_generic_private_init(pTHXo) /* called by dl_*.xs dl_private_init() */
{
@@ -41,6 +69,7 @@ dl_generic_private_init(pTHXo) /* called by dl_*.xs dl_private_init() */
if (!dl_loaded_files)
dl_loaded_files = newHV(); /* provide cache for dl_*.xs if needed */
#endif
+ call_atexit(&dl_unload_all_files, (void*)0);
}
diff --git a/ext/DynaLoader/hints/aix.pl b/ext/DynaLoader/hints/aix.pl
index 4225979320..7dde941b43 100644
--- a/ext/DynaLoader/hints/aix.pl
+++ b/ext/DynaLoader/hints/aix.pl
@@ -3,8 +3,8 @@ use Config;
if ($Config{libs} =~ /-lC/ && -f '/lib/libC.a') {
$self->{CCFLAGS} = $Config{ccflags} . ' -DUSE_libC';
if (-f '/usr/ibmcxx/include/load.h') {
- $self->{CCFLAGS} .= ' -I/usr/ibmcxx/include -DUSE_load_h';
+ $self->{CCFLAGS} .= ' -DUSE_ibmcxx_load_h';
} elsif (-f '/usr/lpp/xlC/include/load.h') {
- $self->{CCFLAGS} .= ' -I/usr/lpp/xlC/include -DUSE_load_h';
+ $self->{CCFLAGS} .= ' -DUSE_xlC_load_h';
}
}