CatalystX-LeakChecker
view release on metacpan or search on metacpan
lib/CatalystX/LeakChecker.pm view on Meta::CPAN
package CatalystX::LeakChecker;
our $VERSION = '0.06';
# ABSTRACT: Debug memory leaks in Catalyst applications
use Moose::Role;
use B::Deparse;
use Text::SimpleTable;
use Scalar::Util 'weaken';
use Devel::Cycle 'find_cycle';
sub deparse {
my ($code) = @_;
return q{sub } . B::Deparse->new->coderef2text($code) . q{;};
}
sub format_table {
my @leaks = @_;
my $t = Text::SimpleTable->new([52, 'Code'], [ 15, 'Variable' ]);
lib/CatalystX/LeakChecker.pm view on Meta::CPAN
my $msg = "Circular reference detected:\n" . $t->draw;
$ctx->log->debug($msg) if $ctx->debug;
}
after finalize => sub {
my ($ctx) = @_;
my @leaks;
my $weak_ctx = $ctx;
weaken $weak_ctx;
find_cycle($ctx, sub {
my ($path) = @_;
push @leaks, $path
if $path->[0]->[2] == $weak_ctx;
});
return unless @leaks;
$ctx->found_leaks(@leaks);
};
t/lib/TestApp/Controller/Affe.pm view on Meta::CPAN
package TestApp::Controller::Affe;
our $VERSION = '0.06';
use Moose;
use Scalar::Util 'weaken';
use namespace::autoclean;
BEGIN { extends 'Catalyst::Controller' }
sub no_closure : Local {
my ($self, $ctx) = @_;
$ctx->response->body('no_closure');
}
sub leak_closure : Local {
my ($self, $ctx) = @_;
$ctx->stash(leak_closure => sub {
$ctx->response->body('from leaky closure');
});
$ctx->response->body('leak_closure');
}
sub weak_closure : Local {
my ($self, $ctx) = @_;
my $weak_ctx = $ctx;
weaken $weak_ctx;
$ctx->stash(weak_closure => sub {
$weak_ctx->response->body('from weak closure');
});
$ctx->response->body('weak_closure');
}
sub leak_closure_indirect : Local {
my ($self, $ctx) = @_;
my $ctx_ref = \$ctx;
$ctx->stash(leak_closure_indirect => sub {
${ $ctx_ref }->response->body('from indirect leaky closure');
});
$ctx->response->body('leak_closure_indirect');
}
sub weak_closure_indirect : Local {
my ($self, $ctx) = @_;
my $ctx_ref = \$ctx;
weaken $ctx_ref;
$ctx->stash(weak_closure_indirect => sub {
${ $ctx_ref }->response->body('from indirect weak closure');
});
$ctx->response->body('weak_closure_indirect');
}
sub stashed_ctx : Local {
my ($self, $ctx) = @_;
$ctx->stash(ctx => $ctx);
$ctx->response->body('stashed_ctx');
}
sub stashed_weak_ctx : Local {
my ($self, $ctx) = @_;
$ctx->stash(ctx => $ctx);
weaken $ctx->stash->{ctx};
$ctx->response->body('stashed_weak_ctx');
}
1;
( run in 1.746 second using v1.01-cache-2.11-cpan-65fba6d93b7 )