1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
|
package Apache::Symbol;
use strict;
use DynaLoader ();
@Apache::Symbol::ISA = qw(DynaLoader);
$Apache::Symbol::VERSION = '1.31';
$Apache::Symbol::DEBUG ||= 0;
use Devel::Symdump ();
sub file2class {
my $file = shift;
return $file unless $file =~ s,\.pm$,,;
$file =~ s,/,::,g;
$file;
}
sub undef_functions {
my( $package, $skip, $only_undef_exports ) = @_;
my $stab = Devel::Symdump->rnew($package);
my @functions = $stab->functions;
if( $only_undef_exports ) {
no strict 'refs';
my $any_export_var;
$any_export_var = 1 if @{$package . "::EXPORT"};
$any_export_var = 1 if @{$package . "::EXPORT_OK"};
$any_export_var = 1 if %{$package . "::EXPORT_TAGS"};
$any_export_var = 1 if @{$package . "::EXPORT_EXTRAS"};
if( $any_export_var ) {
my @names = (@{$package . "::EXPORT"},
@{$package . "::EXPORT_OK"},
@{$package . "::EXPORT_EXTRAS"});
foreach my $tagdata (values %{$package . "::EXPORT_TAGS"}) {
push @names, @$tagdata;
}
my %exported = map { $package . "::" . $_ => 1 } @names;
@functions = grep( $exported{$_}, @functions );
}
}
for my $cv (@functions) {
no strict 'refs';
next if substr($cv, 0, 14) eq "Devel::Symdump";
next if $skip and $cv =~ /$skip/;
#warn "$cv=", *{$cv}{CODE}, "\n";
Apache::Symbol::undef(*{$cv}{CODE});
}
}
sub make_universal {
*UNIVERSAL::undef_functions = \&undef_functions;
}
if($ENV{APACHE_SYMBOL_UNIVERSAL}) {
__PACKAGE__->make_universal;
}
sub handler {
my $fh;
if ($Apache::Symbol::DEBUG) {
require IO::File;
$fh = IO::File->new(">/tmp/Apache::Symbol.debug");
print $fh "Apache::Symbol debug for process $$\n";
}
my $skip = join "|", __PACKAGE__, qw(Devel::Symdump);
my $stab = Devel::Symdump->new('main');
for my $class ($stab->packages) {
next if $class =~ /($skip)/;
if($class->can('undef_functions')) {
print $fh "$class->undef_functions\n" if $fh;
$class->undef_functions;
}
}
close $fh if $fh;
1;
}
bootstrap Apache::Symbol $Apache::Symbol::VERSION;
1;
__END__
=head1 NAME
Apache::Symbol - Things for symbol things
=head1 SYNOPSIS
use Apache::Symbol ();
@ISA = qw(Apache::Symbol);
=head1 DESCRIPTION
B<perlsub/Constant Functions> says:
If you redefine a subroutine which was eligible for inlining you'll get
a mandatory warning. (You can use this warning to tell whether or not a
particular subroutine is considered constant.) The warning is
considered severe enough not to be optional because previously compiled
invocations of the function will still be using the old value of the
function.
I<mandatory warning> means there is _no_ way to avoid this warning
no matter what tricks you pull in Perl. This is bogus for us mod_perl
users when restarting the server with B<PerlFreshRestart> on or when
Apache::StatINC pulls in a module that has changed on disk.
You can, however, pull some tricks with XS to avoid this warning,
B<Apache::Symbol::undef> does just that.
=head1 ARGUMENTS
C<undef_functions> takes two arguments: C<skip> and C<only_undef_exports>.
C<skip> is a regular expression indicating the function names to skip.
Use the C<only_undef_exports> flag to undef only those functions
which are listed in C<@EXPORT>, C<@EXPORT_OK>, C<%EXPORT_TAGS>, or
C<@EXPORT_EXTRAS>. C<@EXPORT_EXTRAS> is not used by the Exporter, it
is only exists to communicate with C<undef_functions>.
As a special case, if none of the EXPORT variables are defined ignore
C<only_undef_exports>. This takes care of trivial modules that don't
use the Exporter.
=head1 ARGUMENTS
C<undef_functions> takes two arguments: C<skip> and C<only_undef_exports>.
C<skip> is a regular expression indicating the function names to skip.
Use the C<only_undef_exports> flag to undef only those functions
which are listed in C<@EXPORT>, C<@EXPORT_OK>, C<%EXPORT_TAGS>, or
C<@EXPORT_EXTRAS>. C<@EXPORT_EXTRAS> is not used by the Exporter, it
is only exists to communicate with C<undef_functions>.
As a special case, if none of the EXPORT variables are defined ignore
C<only_undef_exports>. This takes care of trivial modules that don't
use the Exporter.
=head1 PLAYERS
This module and the undefining of functions is optional, if you wish
to have this functionality enabled, there are one or more switches you
need to know about.
=over 4
=item PerlRestartHandler
Apache::Symbol defines a PerlRestartHandler which can be useful in
conjuction with C<PerlFreshRestart On> as it will avoid subroutine
redefinition messages. Configure like so:
PerlRestartHandler Apache::Symbol
=item Apache::Registry
By placing the SYNOPSIS bit in you script, Apache::Registry will
undefine subroutines in your script before it is re-compiled to
avoid "subroutine re-defined" warnings.
=item Apache::StatINC
See Apache::StatINC's docs.
=item APACHE_SYMBOL_UNIVERSAL
If this environment variable is true when Symbol.pm is compiled,
it will define UNIVERSAL::undef_functions, which means all classes
will inherit B<Apache::Symbol::undef_functions>.
=item Others
Module such as B<HTML::Embperl> and B<Apache::ePerl> who compile
and script cache scripts ala Apache::Registry style can use
C<undef_functions> with this bit of code:
if($package->can('undef_functions')) {
$package->undef_functions;
}
Where C<$package> is the name of the package in which the script is
being re-compiled.
=back
=head1 SEE ALSO
perlsub(1), Devel::Symdump(3)
=head1 AUTHOR
Doug MacEachern
|