Stale %INC cache blocks reloading of edited Perl modules during runtime
0 reputation · 02 Apr 2021, 02:06 UTC
0 reputation · 02 Apr 2021, 02:06 UTC
When a Perl module file is edited on disk while the interpreter is still running, subsequent require or use statements continue to execute the previously loaded version because the absolute path remains stored in the %INC hash.
The goal is to understand why the interpreter does not automatically detect the file change and reload the module, and what considerations affect the decision to manually clear %INC entries or employ a reload mechanism. What are the risks of manually deleting $INC{$module} in a long‑running process? Are there safe patterns for using a development‑only reload module such as Module::Reload without introducing inconsistent state? How can one verify that a stale cache is the cause of unexpected behavior without altering the running program?
Perl utilizes the %INC hash to track which modules have already been loaded. When a use or require statement is executed, the interpreter checks if the module's absolute path exists as a key in %INC. If the key is present, Perl assumes the module is already in memory and skips the file read entirely. Consequently, any changes made to the .pm file on disk while the process is running are ignored because the interpreter never re-examines the source file.
%INC (e.g., delete $INC{'My/Module.pm'};) removes the cache entry, forcing the next require to reload the file from disk.%INC entry does not remove subroutines, variables, or constants already defined in the symbol table. The new version of the module will overwrite existing subroutines, but any state stored in package variables remains unless explicitly reset.%INC. This is typically the path relative to the @INC directories.
delete $INC{'My/Module.pm'};
require 'My/Module.pm';
My::Module->import();
When using tools like Module::Reload, follow these constraints to avoid inconsistent state:
if ($ENV{DEV_MODE}) { ... }).BEGIN blocks or initialization code can be run multiple times without side effects.reset() method to be called immediately after the reload.To confirm a stale cache is the issue without modifying the primary application logic, you can use a debugger or an external signal handler to inspect the process state:
Devel::Peek or a debug shell to check if the module path exists in %INC.$VERSION or a dummy constant to the module. If the running process reports the old version while the disk shows the new one, the %INC entry is stale.Diagnostic Question: Is this process running within a persistent environment such as mod_perl, Plack, or a custom daemon? This determines if the cache must be cleared per-request or only upon specific administrative triggers.
Use comments to ask for clarification. Post a solution as an answer.
32,775 reputation · 02 Apr 2021, 11:19 UTC
To verify a stale %INC entry without altering the running program, compare the path stored in $INC{'Module/Name.pm'} with the current file's modification time using stat. If the on-disk mtime is newer than the process start time, the interpreter is still executing the cached version.
When considering manual deletion, note that modules with XS components or circular require dependencies introduce additional hazards. XS libraries remain loaded in memory even after the Perl-level cache entry is removed, risking symbol clashes. Circular dependencies rely on %INC as a recursion guard; clearing entries can reintroduce partial-load states.
For development workflows, an external file watcher that restarts the worker—such as plackup -R lib for PSGI applications—avoids these in-process hazards entirely.