The first cut at fixing Perl extensions written in C++ in AIX,
Stephanie Beals [Thu, 7 Oct 1999 15:05:54 +0000 (11:05 -0400)]
statics don't get initialized right.  This patch at least
doesn't seem to break the build in my AIX, but unfortunately
I don't have the IBM C++ to do further testing.

Problem reported by Stephanie Beals in
To: perl5-porters@perl.org
Subject: [ID 19991007.005] DynaLoader/dl_aix.xs problem using load and unload on AIX
Message-Id: <85256803.0068E70D.00@D51MTA03.pok.ibm.com>

p4raw-id: //depot/cfgperl@4317

MANIFEST
ext/DynaLoader/dl_aix.xs
ext/DynaLoader/hints/aix.pl [new file with mode: 0644]
hints/aix.sh

index 94ab980..fa96cbe 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -239,6 +239,7 @@ ext/DynaLoader/dl_rhapsody.xs       Rhapsody implementation
 ext/DynaLoader/dl_vmesa.xs     VM/ESA implementation
 ext/DynaLoader/dl_vms.xs       VMS implementation
 ext/DynaLoader/dlutils.c       Dynamic loader utilities for dl_*.xs files
+ext/DynaLoader/hints/aix.pl    Hint for DynaLoader for named architecture
 ext/DynaLoader/hints/linux.pl  Hint for DynaLoader for named architecture
 ext/Errno/ChangeLog            Errno perl module change log
 ext/Errno/Errno_pm.PL          Errno perl module create script
index 18003b2..e3a4113 100644 (file)
 #include <a.out.h>
 #include <ldfcn.h>
 
+/* 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> */
+#ifdef USE_xlC /* The define comes, when it comes, from hints/aix.pl. */
+#   define LOAD   loadAndInitialize
+#   define UNLOAD terminateAndUnload
+#   include <load.h>
+#else
+#   define LOAD   load
+#   define UNLOAD unload
+#endif
+
 /*
  * AIX 4.3 does remove some useful definitions from ldfcn.h. Define
  * these here to compensate for that lossage.
@@ -193,7 +206,7 @@ void *dlopen(char *path, int mode)
         * load should be declared load(const char *...). Thus we
         * cast the path to a normal char *. Ugly.
         */
-       if ((mp->entry = (void *)load((char *)path,
+       if ((mp->entry = (void *)LOAD((char *)path,
 #ifdef L_LIBPATH_EXEC
                                      L_LIBPATH_EXEC |
 #endif
@@ -324,7 +337,7 @@ int dlclose(void *handle)
 
        if (--mp->refCnt > 0)
                return 0;
-       result = unload(mp->entry);
+       result = UNLOAD(mp->entry);
        if (result == -1) {
                errvalid++;
                strerrorcpy(errbuf, errno);
@@ -426,7 +439,7 @@ static int readExports(ModulePtr mp)
                }
                /*
                 * Traverse the list of loaded modules. The entry point
-                * returned by load() does actually point to the data
+                * returned by LOAD() does actually point to the data
                 * segment origin.
                 */
                lp = (struct ld_info *)buf;
diff --git a/ext/DynaLoader/hints/aix.pl b/ext/DynaLoader/hints/aix.pl
new file mode 100644 (file)
index 0000000..e972bfe
--- /dev/null
@@ -0,0 +1,12 @@
+# See dl_aix.xs for details.
+use Config;
+if ($Config{libs} =~ /-lC/ && -f '/lib/libC.a') {
+    $self->{CCFLAGS} = $Config{ccflags} . ' -DUSE_xlC';
+    if (-f '/usr/ibmcxx/include/load.h') {
+       $self->{CCFLAGS} .= ' -I/usr/ibmcxx/include';
+    } elsif (-f '/usr/lpp/xlC/include/load.h') {
+       $self->{CCFLAGS} .= ' -I/usr/lpp/xlC/include';
+    } else {
+       # Hoping that <load.h> will be found somehow.
+    }
+}
index 5a027b3..a8ae6d5 100644 (file)
@@ -2,7 +2,7 @@
 # AIX 3.x.x hints thanks to Wayne Scott <wscott@ichips.intel.com>
 # AIX 4.1 hints thanks to Christopher Chan-Nui <channui@austin.ibm.com>.
 # AIX 4.1 pthreading by Christopher Chan-Nui <channui@austin.ibm.com> and
-#         Jarkko Hietaniemi <jhi@iki.fi>.
+#        Jarkko Hietaniemi <jhi@iki.fi>.
 # Merged on Mon Feb  6 10:22:35 EST 1995 by
 #   Andy Dougherty  <doughera@lafcol.lafayette.edu>
 
@@ -37,7 +37,7 @@
 # pages state:
 #    setrgid: The EPERM error code is always returned.
 #    setruid: The EPERM error code is always returned. Processes cannot
-#             reset only their real user IDs.
+#            reset only their real user IDs.
 d_setrgid='undef'
 d_setruid='undef'
 
@@ -107,8 +107,8 @@ esac
 # The first 3 options would not be needed if dynamic libs. could be linked
 # with the compiler instead of ld.
 # -bI:$(PERL_INC)/perl.exp  Read the exported symbols from the perl binary
-# -bE:$(BASEEXT).exp        Export these symbols.  This file contains only one
-#                           symbol: boot_$(EXP)  can it be auto-generated?
+# -bE:$(BASEEXT).exp       Export these symbols.  This file contains only one
+#                          symbol: boot_$(EXP)  can it be auto-generated?
 case "$osvers" in
 3*) 
     lddlflags="$lddlflags -H512 -T512 -bhalt:4 -bM:SRE -bI:$(PERL_INC)/perl.exp -bE:$(BASEEXT).exp -e _nostart -lc"
@@ -123,48 +123,60 @@ esac
 cat > UU/usethreads.cbu <<'EOCBU'
 case "$usethreads" in
 $define|true|[yY]*)
-        ccflags="$ccflags -DNEED_PTHREAD_INIT"
-        case "$cc" in
-        gcc) ;;
-        cc_r) ;;
-        cc|xlc_r) 
+       ccflags="$ccflags -DNEED_PTHREAD_INIT"
+       case "$cc" in
+       gcc) ;;
+       cc_r) ;;
+       cc|xl[cC]_r) 
            echo >&4 "Switching cc to cc_r because of POSIX threads."
            # xlc_r has been known to produce buggy code in AIX 4.3.2.
-           # (e.g. pragma/overload core dumps)
+           # (e.g. pragma/overload core dumps)  Let's suspect xlC_r, too.
            # --jhi@iki.fi
            cc=cc_r
            if test ! -e /bin/cc_r; then
-                   cat >&4 <<EOM
+                   cat >&4 <<EOM
 For pthreads you should use the AIX C compiler cc_r.
-But I cannot find it in /bin.
+But I cannot find it as /bin/cc_r.
 Cannot continue, aborting.
 EOM
            fi
-            ;;
-        '') 
+           ;;
+       '') 
            cc=cc_r
-            ;;
-        *)
-           cat >&4 <<EOM
+           ;;
+       *)
+           cat >&4 <<EOM
 For pthreads you should use the AIX C compiler cc_r.
 (now your compiler was set to '$cc')
 Cannot continue, aborting.
 EOM
-           exit 1
+           exit 1
            ;;
-        esac
-
-        # Add the POSIX threads library and the re-entrant libc to lddflags.
-        set `echo X "$lddlflags"| sed -e 's/ -lc$/ -lpthreads -lc_r/'`
-        shift
-        lddlflags="$*"
-
-        # Add the POSIX threads library and the re-entrant libc to libswanted.
-        # Make sure the c_r library is before the c library or
-        # make will fail.
-        set `echo X "$libswanted "| sed -e 's/ c / pthreads c_r /'`
-        shift
-        libswanted="$*"
+       esac
+
+       # The libC_r is to be preferred over the libc_r because otherwise
+       # extensions written in C++ using statics won't be initialized right;
+       # see ext/DynaLoader/dl_aix.xs.
+       if test -f /lib/libC_r.a; then
+           # C_rify libwanted.
+           set `echo X "$libswanted "| sed -e 's/ C / pthreads C_r /'`
+           shift
+           libswanted="$*"
+           # C_rify lddlflags.
+           set `echo X "$lddlflags"| sed -e 's/ -lc$/ -lpthreads -lC_r/'`
+           shift
+           lddlflags="$*"
+       else
+           # The POSIX threads library and the re-entrant libc to libswanted.
+           set `echo X "$libswanted "| sed -e 's/ c / pthreads c_r /'`
+           shift
+           libswanted="$*"
+
+           # The POSIX threads library and the re-entrant libc to lddflags.
+           set `echo X "$lddlflags"| sed -e 's/ -lc$/ -lpthreads -lc_r/'`
+           shift
+           lddlflags="$*"
+       fi
        ;;
 esac
 EOCBU
@@ -183,7 +195,7 @@ EOM
                exit 1
                ;;
            esac
-           ccflags="$ccflags -DUSE_LONG_LONG"
+           ccflags="$ccflags -DUSE_LONG_LONG"
            ccflags="$ccflags `getconf XBS5_ILP32_OFFBIG_CFLAGS 2>/dev/null`"
 
            ldflags="$ldflags `getconf XBS5_ILP32_OFFBIG_LDFLAGS 2>/dev/null`"
@@ -193,10 +205,10 @@ EOM
            # (nothing strange shows up in $ldflags even in hexdump;
            #  so it may be something in the shell, instead?)
            # Try it out: just uncomment the below line and rerun Configure:
-#          echo >& "AIX $ldflags mystery" ; exit 1
+#          echo >&4 "AIX $ldflags mystery" ; exit 1
            # Just don't ask me how AIX does it.
            # Therefore the line re-evaluating ldflags: it seems to bypass
-           # the whatever it was AIX managed to break. --jhi
+           # the whatever it was that AIX managed to break. --jhi
            ldflags="`echo $ldflags`"
 
            libswanted="$libswanted `getconf XBS5_ILP32_OFFBIG_LIBS 2>/dev/null|sed -e 's@^-l@@' -e 's@ -l@ @g'`"
@@ -212,8 +224,17 @@ cat > UU/uselongdouble.cbu <<'EOCBU'
 case "$uselongdouble" in
 $define|true|[yY]*)
        ccflags="$ccflags -qlongdouble"
+       # The explicit cc128, xlc128, xlC128 are not needed,
+       # the -qlongdouble should do the trick. --jhi
        ;;
 esac
 EOCBU
 
+# If the C++ libraries, libC, are available we will prefer them over
+# the vanilla libc, because the libC contain loadAndInitialize() and
+# terminateAndUnload() which work correctly with C++ statics while libc
+# load() and unload() do not.  See ext/DynaLoader/dl_aix.xs.
+# The c_r-to-C_r switch is done by usethreads.cbu.
+test -f /lib/libC.a && libswanted=`$echo " $libswanted "|sed -e 's/ c / C /'`
+
 # EOF