Hi Roderich,
I thought some more about this:
Roderich Schupp wrote:
- How can modifying find_par_last help in implementing "fallback => 0", i.e.
"prefer loading modules from a repository over the locally installed modules",
when find_par_last is _appended_ to @INC: if a module is already found using
the built-in @INC the find_par_last will not be called at all?
Actually, it's find_par that's modified between 0.991 and 0.992.
find_par_last has "always" been the place where repositories were checked.
- If find_par_last works as intended, why is there no corresponding
modification for the code path dealing with bootstrapping DLLs, i.e. XS parts?
The modification to find_par_last in 0.992 explicitly deals only
with .pm files.
The function in PAR.pm that replaces DynaLoader::bootstrap still calls
_find_par_any.
Hmm. Let me explain the logic a bit. Maybe you can spot what's wrong
with it (I can't). First, without repositories:
- There's a list of .par files that have been loaded preferentially.
They take precedence over the installed modules and are tracked via the
list in @PAR_INC.
- Then, there's a list of .par's which are considered fallbacks. They
are tracked in the last @PAR_INC_LAST.
- When a module's used, the first @INC entry is a hook (find_par) that
tries to load he modules from the .pars in @PAR_INC. If that fails, @INC
is trawled normally until it hits the last hook (find_par_last). That
one checks the .pars in @PAR_INC_LAST.
- When a module tries to load a shared library via DynaLoader it
triggers _find_par_any. That one simply calls _find_par_internals (just
like find_par and find_par_last if you disregard repositories), but
instead of passing either @PAR_INC or @PAR_INC_LAST, it passes both, so
the shared library is sought in either place. If it's not found, control
is handed to the ordinary DynaLoader bootstrap routine.
==> Here's where I guess there might be a bug: Since the overridden
bootstrap routine searches ALL pars before handing control back to
DynaLoader. That means it will happily load shared libraries from the
fallback pars even if it should have checked the system first. I'll try
a hacky fix for this later.
With repositories, things become a bit more complicated:
- If any repository that's checked for a particular module has it, the
corresponding par file will be downloaded to the computer and loaded
with PAR. Therefore, it'll feed back into the @PAR_INC or @PAR_INC_LAST
lists of loaded pars at that point (see above).
- If there are repositories in upgrade mode, they are checked first in
find_par. (First hook in @INC)
- After checking for the upgrade repositories, PAR_INC is checked as
usual. Then comes checking @PriorityRepositoryObjects, which is
repositories with "fallback => 0" set. This is the new addition in 0.992!
==> Now that I looked at the code some more, it seems there may be
another bug here: If one of those fallback=>0 repositories returns a
hit, the par is loaded but appended to @PAR_INC_LAST. That means any
modules that may still be loaded from those PAR's will suddenly live at
the end of the priority chain!
- Finally, the find_par_last routine will first try locally loaded PAR
files (including those from repositories) with fallback=>1 and then
repositories.
Now, I don't think that the DynaLoader override needs to know about
repositories. That's because repositories don't track all files anyway
but only modules. It's probably a rather good assumption to expect only
shared libraries for modules to be required that have just been loaded
from the repository anyway.
Cheers,
Steffen