[prev in list] [next in list] [prev in thread] [next in thread] 

List:       perl-qa
Subject:    Re: scary and strange thing in FindBin
From:       Eric Wilhelm <scratchcomputing () gmail ! com>
Date:       2008-08-11 5:14:28
Message-ID: 200808102214.28421.ewilhelm () cpan ! org
[Download RAW message or body]

# from Aristotle Pagaltzis
# on Sunday 10 August 2008 19:30:

>>> See Tom Heady's reply on this thread.
>>
>> Which also as issues, albeit maybe fewer.
>
>Yes, it will fail in some very rare cases. However, it does so loudly
>and predictably. 

Oh?  'chdir dirname( rel2abs( $0 ) );' doesn't look to me to contain the 
loud and predictable 'or die'

>FindBin tries to avoid failing by employing
>heuristics, and as we all know that is a fancy word for saying
>"it doesn't work."

I guess we like to call it a heuristic, because that makes it sound like 
we're solving some complicated and mathematically difficult problem?
But "mistake" has fewer letters and doesn't imply that locating a 
directory somehow requires the Ramsey number for red six and blue six.

In the case of Makefile.PL wanting to know where it is, I think anything 
involving rel2abs is probably overkill, and $0 could quite likely be 
incorrect on account of do(), so all you really want is 
dirname(__FILE__), right?  Of course, if you're going to go through the 
loop of resolving symlinks, you do need to deal with things having been 
relative (assuming of course that what you wanted was to know the 
location of the file at the end of whatever number of symlinks (and 
that you didn't mind if a hardlink was involved because then we have to 
run find on the entire partition and compare inodes (which clearly 
FindBin should have done (but probably several steps after it 
checked -e $0, which it did not (but that would have been a nifty first 
step.)))))

But in this particular case, does everything else in the world not 
already explode anyway unless(-e './Makefile.PL')?

As for solving the generic case, you still have to account for PAR, and 
the fact that $0 might be '-e', or could simply be relative to wherever 
we were before a chdir(), at which point we should probably just 
exec('/usr/bin/eject', '.') in order to achieve suitable predictable 
loudness.

But yes, the FindBin code is wrong, and so is the documentation.

  "If perl is invoked as C<perl filename> and I<filename> does not have
  executable rights and a program called I<filename> exists in the users
  C<$ENV{PATH}> which satisfies both B<-x> and B<-T> then FindBin
  assumes that it was invoked via the C<$ENV{PATH}>."

Should have just said: "if $0 !~ m#/# and a program called ..."

It seems like something using import() and caller() might generate a 
more predictable solution with fewer caveats (such as hating to be 
called twice, assuming $0, etc.)  It could possibly even defer the 
symlink resolution bit until it was actually needed.

  use File::WhereAmI;
  my $where = File::WhereAmI->real_directory;
  my $there = File::WhereAmI->where_is_who("Bar.pm")->filename;


But in Makefile.PL land, all of the necessary simplifying assumptions 
were made long ago.

  $ cd /tmp
  $ perl /wherever/Makefile.PL
    Could not open 'lib/Foo.pm':
      No such file or directory at .../ExtUtils/MM_Unix.pm line 2708.

--Eric
-- 
"Unthinking respect for authority is the greatest enemy of truth."
--Albert Einstein
---------------------------------------------------
    http://scratchcomputing.com
---------------------------------------------------

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic