Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Relocatable-perl on AIX does not run if added to PATH #11453

Open
p5pRT opened this issue Jun 20, 2011 · 14 comments
Open

Relocatable-perl on AIX does not run if added to PATH #11453

p5pRT opened this issue Jun 20, 2011 · 14 comments

Comments

@p5pRT
Copy link

p5pRT commented Jun 20, 2011

Migrated from rt.perl.org#93134 (status was 'open')

Searchable as RT93134$

@p5pRT
Copy link
Author

p5pRT commented Jun 20, 2011

From @dmcbride

Created by @dmcbride

If I compile perl 5.14.0 with -Duserelocatableinc, and then relocate
it afterward and add that to the PATH, "perl -V" doesn't find Config.pm
and thus dies.

$ perl -v

This is perl 5, version 14, subversion 0 (v5.14.0) built for aix-thread-multi-64all

Copyright 1987-2011, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl". If you have access to the
Internet, point your browser at http​://www.perl.org/, the Perl Home Page.

$ perl -V
Can't locate Config.pm in @​INC (@​INC contains​: ../lib/site_perl/5.14.0/aix-thread-multi-64all ../lib/site_perl/5.14.0 ../lib/5.14.0/aix-thread-multi-64all ../lib/5.14.0 .).

When I try this on Linux, it works. I suspect it has something to do with​:

$ perl -le 'print $^X'
perl

whereas if I do the same thing on Linux, I get a full path to perl in the
relocated directory (not where it was compiled to install to). If I call
the perl on AIX with a full or relative path, it works fine.

Note that if I run perlbug, whether on AIX or Linux, it fails. The #!
line combined with the eval 'exec ...' simply fail to find the perl it's
associated with, e.g., on Linux​:

$ perlbug
bash​: /home/dmcbride/perl/tmp/foo/usr/opt/perl/bin/perlbug​: /usr/opt/perl/bin/perl​: bad interpreter​: No such file or directory

Perl Info

Flags:
    category=core
    severity=low

Site configuration information for perl 5.14.0:

Configured by dmcbride at Thu Jun 16 12:35:56 EDT 2011.

Summary of my perl5 (revision 5 version 14 subversion 0) configuration:
   
  Platform:
    osname=aix, osvers=6.1.0.0, archname=aix-thread-multi-64all
    uname='aix hotelisasp01 1 6 00c1837d4c00 '
    config_args='-d -Dcc=cc_r -Dusethreads -Duse64bitall -Dprefix=/opt/perl -Duserelocatableinc'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=define, usemultiplicity=define
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=define, use64bitall=define, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc_r -q64', ccflags ='-D_ALL_SOURCE -D_ANSI_C_SOURCE -D_POSIX_SOURCE -qmaxmem=-1 -qnoansialias -DUSE_NATIVE_DLOPEN -DNEED_PTHREAD_INIT -q64 -DUSE_64_BIT_ALL -q64',
    optimize='-O',
    cppflags='-D_ALL_SOURCE -D_ANSI_C_SOURCE -D_POSIX_SOURCE -qmaxmem=-1 -qnoansialias -DUSE_NATIVE_DLOPEN -DNEED_PTHREAD_INIT'
    ccversion='10.1.0.2', gccversion='', gccosandvers=''
    intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=87654321
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=8
    ivtype='long long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='ld', ldflags ='-brtl -bdynamic -b64'
    libpth=/lib /usr/lib /usr/ccs/lib
    libs=-lbind -lnsl -ldbm -ldl -lld -lm -lcrypt -lpthreads -lc
    perllibs=-lbind -lnsl -ldl -lld -lm -lcrypt -lpthreads -lc
    libc=/lib/libc.a, so=a, useshrplib=false, libperl=libperl.a
    gnulibc_version=''
  Dynamic Linking:
    dlsrc=dl_aix.xs, dlext=so, d_dlsymun=undef, ccdlflags='  -bE:.../../lib/5.14.0/aix-thread-multi-64all/CORE/perl.exp'
    cccdlflags=' ', lddlflags='-b64 -bhalt:4 -G -bI:$(PERL_INC)/perl.exp -bE:$(BASEEXT).exp -bnoentry -lpthreads -lc -lm'

Locally applied patches:
    


@INC for perl 5.14.0:
    newperl/opt/perl/lib/site_perl/5.14.0/aix-thread-multi-64all
    newperl/opt/perl/lib/site_perl/5.14.0
    newperl/opt/perl/lib/5.14.0/aix-thread-multi-64all
    newperl/opt/perl/lib/5.14.0
    .


Environment for perl 5.14.0:
    HOME=/home/dmcbride
    LANG=en_US
    LANGUAGE (unset)
    LC__FASTMSG=true
    LD_LIBRARY_PATH (unset)
    LIBPATH (unset)
    LOGDIR (unset)
    PATH=/usr/bin:/etc:/usr/sbin:/usr/ucb:/home/dmcbride/bin:/usr/bin/X11:/sbin:.
    PERL_BADLANG (unset)
    SHELL=/usr/bin/ksh

@p5pRT
Copy link
Author

p5pRT commented Jun 21, 2011

From @jandubois

On Mon, 20 Jun 2011, via RT wrote​:

If I compile perl 5.14.0 with -Duserelocatableinc, and then relocate
it afterward and add that to the PATH, "perl -V" doesn't find Config.pm
and thus dies.

[...]

When I try this on Linux, it works. I suspect it has something to do with​:

$ perl -le 'print $^X'
perl

whereas if I do the same thing on Linux, I get a full path to perl in the
relocated directory (not where it was compiled to install to). If I call
the perl on AIX with a full or relative path, it works fine.

That is indeed the problem​: -Duserelocatableinc really only works on Linux
where $^X is set from /proc/self/exe. On other systems it just relies on the
value of argv[0], which is typically not fully qualified.

I know how to make things work on OS X and Solaris as well, but for AIX
and HP-UX I don't know of any secure/reliable mechanism to determine
the full path of the currently running executable.

On Windows this is not an issue as there @​INC is always determined at runtime
relative to the location of the perl5xx.dll file.

Cheers,
-Jan

@p5pRT
Copy link
Author

p5pRT commented Jun 21, 2011

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Jun 21, 2011

From darin.mcbride@shaw.ca

You mention that you don't know how on HPUX (which I don't care
about right now), but searching for the AIX solution popped this up -
the "pstat" answer looks most promising. I'm still searching for AIX.

http​://stackoverflow.com/questions/200737/get-full-path-of-
executable-of-running-process-on-hpux

@p5pRT
Copy link
Author

p5pRT commented Sep 28, 2011

From @nwc10

On Mon, Jun 20, 2011 at 04​:59​:33PM -0700, Jan Dubois wrote​:

On Mon, 20 Jun 2011, via RT wrote​:

If I compile perl 5.14.0 with -Duserelocatableinc, and then relocate
it afterward and add that to the PATH, "perl -V" doesn't find Config.pm
and thus dies.

[...]

When I try this on Linux, it works. I suspect it has something to do with​:

$ perl -le 'print $^X'
perl

whereas if I do the same thing on Linux, I get a full path to perl in the
relocated directory (not where it was compiled to install to). If I call
the perl on AIX with a full or relative path, it works fine.

That is indeed the problem​: -Duserelocatableinc really only works on Linux
where $^X is set from /proc/self/exe. On other systems it just relies on the
value of argv[0], which is typically not fully qualified.

I know how to make things work on OS X and Solaris as well, but for AIX
and HP-UX I don't know of any secure/reliable mechanism to determine
the full path of the currently running executable.

With commit 6f31bef I've merged code to make $^X absolute on OS X,
Solaris 10 and 11, and FreeBSD without needing /proc mounted.

It would be possible to use getexecname() along with realpath() on earlier
Solaris, but I'm not sure if it's worth adding.

perl already uses /proc on Linux and NetBSD to convert $^X to an absolute
path.

Like Jan, I'm not aware of a reliable way to do this on any other platform.
Likely it's not possible.

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented Sep 28, 2011

From @icerider70

On Wed, Sep 28, 2011 at 5​:43 AM, Nicholas Clark <nick@​ccl4.org> wrote​:

Like Jan, I'm not aware of a reliable way to do this on any other platform.
Likely it's not possible.

The following code snippet (found via stackoverflow), appears to work as
advertised on HP-UX 11.23 and 11.31​:

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <unistd.h>

#define _PSTAT64
#include <sys/pstat.h>

int main(int argc, char *argv[])
{
  char filename[PATH_MAX];
  struct pst_status s;

  if (pstat_getproc(&s,sizeof(s),0,getpid()) == -1) {
  perror("pstat_getproc");
  return EXIT_FAILURE;
  }

  if (pstat_getpathname(filename,sizeof(filename),&s.pst_fid_text) == -1) {
  perror("pstat_getpathname");
  return EXIT_FAILURE;
  }

  printf("filename​: %s\n",filename);

  return EXIT_SUCCESS;
}

--Phil

@p5pRT
Copy link
Author

p5pRT commented Sep 28, 2011

From @nwc10

On Wed, Sep 28, 2011 at 12​:13​:49PM -0500, Philip Monsen wrote​:

On Wed, Sep 28, 2011 at 5​:43 AM, Nicholas Clark <nick@​ccl4.org> wrote​:

Like Jan, I'm not aware of a reliable way to do this on any other platform.
Likely it's not possible.

Good. Proven wrong on another platform. Are the rest "impossible" too? :-)

The following code snippet (found via stackoverflow), appears to work as
advertised on HP-UX 11.23 and 11.31​:

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <unistd.h>

#define _PSTAT64
#include <sys/pstat.h>

int main(int argc, char *argv[])
{
char filename[PATH_MAX];
struct pst_status s;

if (pstat_getproc(&s,sizeof(s),0,getpid()) == -1) {
perror("pstat_getproc");
return EXIT_FAILURE;
}

I don't have access to any HP-UX system, so can't write code to test
any of this. I think that the right approach would be a Configure probe,
perl.c change analogous to those for sysctl() and _NSGetExecutablePath()

http​://perl5.git.perl.org/perl.git/commit/2982a345b7a1edb6
http​://perl5.git.perl.org/perl.git/commit/ae60cb464cebf895

[the second patch was based on the first]

From searching online I find this piece of documentation​:

  On success, the function returns the length of the
  pathname copied starting at the location specified by
  buf. If the pathname is not available in the system
  cache, 0 is returned and errno is not set. On other
  failures, the value of -1 is returned and errno is set
  indicating the cause of the failure. This call does not
  work for sockets.

if (pstat_getpathname(filename,sizeof(filename),&s.pst_fid_text) == -1) {
perror("pstat_getpathname");
return EXIT_FAILURE;
}

printf("filename​: %s\n",filename);

return EXIT_SUCCESS;
}

Which the sample code would fall foul of. I'm wondering what other
gotchas are involved. The code you quote allowed me to find a link to
this​: http​://h21007.www2.hp.com/portal/site/dspp/menuitem.863c3e4cbcdc3f3515b49c108973a801?ciid=88086d6e1de021106d6e1de02110275d6e10RCRD

which has this​:

Alternate program for 64-bit

#include <dlfcn.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
  struct load_module_desc desc;
  char *name;
  dlget(-2, &desc, sizeof(desc));
  name = dlgetname(&desc, sizeof(desc), NULL, NULL, NULL);
  printf("executable is '%s' (from dlgetname).\n", name);
  return 0;
}

I have *no* idea of the relative merits of the two approaches when both
are available. The latter looks less complex, and less prone to failure,
but I've no idea what downsides it has.

Nicholas Clark
 

@p5pRT
Copy link
Author

p5pRT commented Sep 28, 2011

From @icerider70

On Wed, Sep 28, 2011 at 1​:21 PM, Nicholas Clark <nick@​ccl4.org> wrote​:

I have *no* idea of the relative merits of the two approaches when both
are available. The latter looks less complex, and less prone to failure,
but I've no idea what downsides it has.

Unfortunately, the main downside is that it doesn't actually appear to
provide a full path​:

# On both 11.23 and 11.31
$ ./my_dlget
executable is './my_dlget' (from dlgetname).

I'm wondering if some guarantee is afforded for a process's executable name
to be in the directory name lookup cache (DNLC) if its process information
is queried immediately prior via pstat_getproc(), as in the first code
snippet. If there were, then there'd be more assurance that
pstat_getpathname() would return reliable information. The pstat docs don't
say so (at least it doesn't jump right out), but since the DNLC is dumpable
(per filesystem) via pstat_getmpathname(), maybe it's possible to make some
judgments based on empirical observation.

--Phil

@p5pRT
Copy link
Author

p5pRT commented Sep 28, 2011

From @icerider70

On Wed, Sep 28, 2011 at 2​:07 PM, Philip Monsen <philip.monsen@​gmail.com>wrote​:

I'm wondering if some guarantee is afforded for a process's executable name
to be in the directory name lookup cache (DNLC) if its process information
is queried immediately prior via pstat_getproc(), as in the first code
snippet. If there were, then there'd be more assurance that
pstat_getpathname() would return reliable information. The pstat docs don't
say so (at least it doesn't jump right out), but since the DNLC is dumpable
(per filesystem) via pstat_getmpathname(), maybe it's possible to make some
judgments based on empirical observation.

Doing this empirical test is pretty much a non-starter for me given the
restriction to use of pstat_getmpathname() from the manpage, and my local
lack of the required credentials​:

  The use of this function is limited to UID 0.

--Phil

@p5pRT
Copy link
Author

p5pRT commented Dec 11, 2011

From tammer@tammer.net

Hello,
OK, you are looking for something like this on AIX, but in C without the
use of system tools​:


#!/usr/bin/perl

@​proc = split/ /,`procfiles $$|head -n 1`;
if (-l $proc[2])
{
  print `readlink $proc[2]`;
}
else
{
  print "$proc[2]\n";
}

exit 0;


# ./test.pl
/usr/opt/perl5/bin/perl5.8.2

Bye
  Rainer

@p5pRT
Copy link
Author

p5pRT commented Mar 23, 2016

From gskallur@gmail.com

This issue is there in perl 5.22.0 in AIX and HPIA.
Please let me know if there is a work around

@p5pRT
Copy link
Author

p5pRT commented Mar 23, 2016

From [Unknown Contact. See original ticket]

This issue is there in perl 5.22.0 in AIX and HPIA.
Please let me know if there is a work around

@p5pRT
Copy link
Author

p5pRT commented Mar 23, 2016

From gskallur@gmail.com

For HP-UX below approach is working. Can some one please validate.

Added the following code in perl_source/caretx.c

# elif defined(__hpux)
  #include <dlfcn.h>
  struct load_module_desc desc;
  char *name;
  dlget(-2, &desc, sizeof(desc));
  name = dlgetname(&desc, sizeof(desc), NULL, NULL, NULL);
  sv_setpv(caret_x, name);
  return;

@p5pRT
Copy link
Author

p5pRT commented Mar 23, 2016

From [Unknown Contact. See original ticket]

For HP-UX below approach is working. Can some one please validate.

Added the following code in perl_source/caretx.c

# elif defined(__hpux)
  #include <dlfcn.h>
  struct load_module_desc desc;
  char *name;
  dlget(-2, &desc, sizeof(desc));
  name = dlgetname(&desc, sizeof(desc), NULL, NULL, NULL);
  sv_setpv(caret_x, name);
  return;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants