Question

I have a forking server. I load all modules before I fork.

...or do I? I want a message to be logged to STDERR for every module loaded after a certain point in my program.

I was going to use the following, but it's logging some scripts executed using do.

my %ignore = map { $_ => 1 } ( ... );
unshift @INC, sub {
   my (undef, $path) = @_;
   warn("$path wasn't loaded before forking.\n")
      if !$ignore{$path};

   return ();
};

I'm not out of ideas, but before I spend more time on this, I was wondering if there's an existing solution.

Was it helpful?

Solution 2

Solution:

my $old_require =
   defined(&CORE::GLOBAL::require)
      ? \&CORE::GLOBAL::require
      : sub { CORE::require($_[0]) };

my $new_require = sub {
   my $path = shift;
   if ($INC{$path}) {
      return $old_require->($path);
   }

   my $rv = $old_require->($path);
   warn("Loaded $path after fork\n");
   return $rv;
};

no warnings 'redefine';
*CORE::GLOBAL::require = $new_require;

The solution has the following features:

  • Logs modules loaded by require EXPR.
  • Logs modules loaded by require BAREWORD.
  • Logs modules loaded by use BAREWORD.
  • Ignores code loaded by do EXPR.
  • Ignores modules that fail to load.
  • Ignores modules that have already been loaded.
  • Works even if @INC is manipulated.

The last four were problems experienced by the solution in the OP. I can't find any downsides to this solution.

OTHER TIPS

What things are using do? Is simply

if $path =~ /\.pm\z/ && !$ignore{$path};

good enough to distinguish?

Other options:

Static code analysis with PPI (using or based on Module::Extract::Use).

Dump %INC to a file upon SIGHUP or some other signal.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top