Skip to content

Instantly share code, notes, and snippets.

@avar
Last active August 29, 2015 13:56
Show Gist options
  • Select an option

  • Save avar/8809976 to your computer and use it in GitHub Desktop.

Select an option

Save avar/8809976 to your computer and use it in GitHub Desktop.
Some code snippets of code I'm using to detect when Mason clobbers subroutines in HTML::Mason::Commands during a request
## Utility function to get a copy of subroutines in a given namespace:
sub copy_of_code_symbols {
my ($symbol_table) = @_;
my %copy = map {
+($_ => *{$symbol_table->{$_}}{CODE});
} grep {
my $name = $_;
# Maybe it's not a code symbol
my $reftype = '';
eval {
# Not all of them are globs, e.g. constants defined by
# constant.pm. Easier just to check these with eval.
$reftype = ref *{$symbol_table->{$name}}{CODE};
1;
} or do {
my $error = $@ || "Zombie Error";
#use Data::Dump::Streamer;
#Dump({error => [$name => $error => $symbol_table->{$name}]})->To(\*STDERR)->Out();
};
$reftype eq 'CODE';
} keys %$symbol_table;
return \%copy;
}
# We'll set $EXECUTED_MASON if we executed a Mason page during the
# request, $MASON_SUBS_AT_REQUEST_START is set after we finish this
# request, or as a special case just after we fork the webserver
# child:
# Under Mason all templates are compiled into the
# HTML::Mason::Commands namespace. We want to figure out the
# difference between the symbols before and after all requests, so
# we can report on any clobbered subroutines.
if (MASON_DETECT_CLOBBERED_SUBROUTINES and $EXECUTED_MASON) {
my (@sub_same, @sub_clobbered, @sub_added);
my $subs_before = $MASON_SUBS_AT_REQUEST_START;
my $subs_after = copy_of_code_symbols(\%HTML::Mason::Commands::);
for my $sub (sort keys %$subs_after) {
if (exists $subs_before->{$sub}) {
# This request added a sub to HTML::Mason::Commands,
# which is fine unless an existing sub was
# clobbered. "Fine" here is relative, we'll eventually
# end up with a *huge* symbol table, but who cares as
# long as we don't have collisions...
if ($subs_before->{$sub} != $subs_after->{$sub}) {
push @sub_clobbered => $sub;
} else {
push @sub_same => $sub if DEBUG;
}
} else {
push @sub_added => $sub if DEBUG;
}
}
TELL "We went from <%d> to <%d> subs in HTML::Mason::Commands. That's <%d> added, <%d> are the same, <%d> were clobbered",
scalar(keys %$subs_before),
scalar(keys %$subs_after),
scalar(@sub_added),
scalar(@sub_same),
scalar(@sub_clobbered)
if DEBUG;
if (@sub_clobbered) {
warn "During this Mason request we clobbered one or more HTML::Mason::Commands subs\n"
. "\n"
. "We clobbered <" . scalar(@sub_clobbered) . "> of them: <" . join(", ", @sub_clobbered) . ">\n"
. "\n"
. "Note that the stack trace displayed here isn't significant, but\n"
. "it should be fairly easy to find the symbol that's being\n"
. "clobbered by grepping around in the source of the Mason page that\n"
. "we just rendered, or the components that it used\n"
. "\n"
. "Both the symbol that's being clobbered and the symbol that\n"
. "clobbered it represent a bug that we should fix, by either\n"
. "renaming the subs so that their names don't collide, or better\n"
. "yet just don't import them into the HTML::Mason::Commands\n"
. "namespace in the first place.";
}
# Record the current symbols so the next request can
# potentially whine about them.
$MASON_SUBS_AT_REQUEST_START = copy_of_code_symbols(\%HTML::Mason::Commands::);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment