in reply to Re^3: Do modules know the callers full path?
in thread Do modules know the callers full path?

I tested my solution from a module too and it's unlikely such a chdir happens at compile time before a module is used.

Especially since a BEGIN { chdir ".." } also effects relative paths in @INC.

Granted I was too lazy posting two files.

So I'd speculate this approach is good enough for the OPs cases.

Modules can be loaded at run time. And that will break any code that relies on a constant working directory.

Load a simple module at run time from a simple script and have the module report where the main script is:

/tmp/perlmonks>cat run.pl #!/usr/bin/perl use strict; use warnings; use lib '/tmp/perlmonks'; # Tons of work omitted ... ;-) @ARGV and chdir '/tmp/unrelated'; require Mod; Mod::where(); /tmp/perlmonks>cat Mod.pm package Mod; use v5.12; # for say use strict; use warnings; use FindBin; sub where { say "Script is in $FindBin::Bin"; say "Script basename is $FindBin::Script"; say "Real script directory is $FindBin::RealBin"; say "Real script basename is $FindBin::RealScript"; say "Module was loaded from $INC{'Mod.pm'}"; } 1; /tmp/perlmonks>perl run.pl Script is in /tmp/perlmonks Script basename is run.pl Real script directory is /tmp/perlmonks Real script basename is run.pl Module was loaded from /tmp/perlmonks/Mod.pm /tmp/perlmonks>

That works even from the command line:

/tmp/perlmonks>perl -MMod -e Mod::where Script is in /tmp/perlmonks Script basename is -e Real script directory is /tmp/perlmonks Real script basename is -e Module was loaded from Mod.pm /tmp/perlmonks>

Run the script again, but this time, change the working directory before loading the module:

/tmp/perlmonks>perl run.pl x Cannot find current script 'run.pl' at /usr/share/perl5/FindBin.pm lin +e 166. BEGIN failed--compilation aborted at /usr/share/perl5/FindBin.pm line +166. Compilation failed in require at /tmp/perlmonks/Mod.pm line 6. BEGIN failed--compilation aborted at /tmp/perlmonks/Mod.pm line 6. Compilation failed in require at run.pl line 11. /tmp/perlmonks>

Obviously, FindBin has some tests to prevent accidents, but they can be defeated:

/tmp/perlmonks>touch /tmp/unrelated/run.pl /tmp/perlmonks>perl run.pl Script is in /tmp/unrelated Script basename is run.pl Real script directory is /tmp/unrelated Real script basename is run.pl Module was loaded from /tmp/perlmonks/Mod.pm /tmp/perlmonks>

Now, FindBin is sure that the main script is /tmp/unrelated/run.pl. It is not.

To fix that problem, load FindBin as early as possible from the main script, or even via command line parameters:

/tmp/perlmonks>perl -MFindBin run.pl x Script is in /tmp/perlmonks Script basename is run.pl Real script directory is /tmp/perlmonks Real script basename is run.pl Module was loaded from /tmp/perlmonks/Mod.pm /tmp/perlmonks>

Oh, by the way, this is not the problem from the FindBin documentation. FindBin documents a different problem, with persistent environments like mod_perl:

KNOWN ISSUES

If there are two modules using FindBin from different directories under the same interpreter, this won't work. Since FindBin uses a BEGIN block, it'll be executed only once, and only the first caller will get it right. This is a problem under mod_perl and other persistent Perl environments, where you shouldn't use this module. Which also means that you should avoid using FindBin in modules that you plan to put on CPAN.

Alexander

--
Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)

Replies are listed 'Best First'.
Re^5: Do modules know the callers full path?
by LanX (Saint) on Feb 16, 2023 at 18:39 UTC
    > To fix that problem, load FindBin as early as possible from the main script,

    yeah sure but the question was related to what the module can know.

    I offered a best practical solution (quote: good enough for the OPs cases )

    The only perfect solution - apart of amending the Perl binary - that I can see is to tweak the Config.pm of the local Perl installation to always save the original CWD at start time.

    Cheers Rolf
    (addicted to the 𐍀𐌴𐍂𐌻 Programming Language :)
    Wikisyntax for the Monastery