Skip Menu |

Preferred bug tracker

Please visit the preferred bug tracker to report your issue.

This queue is for tickets about the Email-MIME CPAN distribution.

Report information
The Basics
Id: 7007
Status: resolved
Priority: 0/
Queue: Email-MIME

People
Owner: Nobody in particular
Requestors: scott [...] perlcode.org
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in: 1.7
Fixed in: (no value)



Subject: parts_single_part causes memory leak
Email::MIME::parts_single_part creates a self-referencing object: $self->{parts} = [ $self ]; this memory is never freed until the process terminates. For long-lived processes where Email::MIME is used to parts many messages, the leak can be significant. Here is some code that will output 'ps' for bsd-ish systems: <snip> #!/usr/local/bin/perl -w use strict; use Email::MIME; for ( 1 .. 1000 ) { my $msg = <<'_MESSAGE_'; Date: Mon, 28 Jun 2004 23:22:26 -0600 From: Scott Wiersdorf <scott@perlcode.org> To: root@nowhere.tld Subject: Hokey Pokey Everybody do the hokey pokey. _MESSAGE_ ## this same message parsed with Email::Simple does not leak Email::MIME->new($msg); ## parse and throw away printf STDERR "LOOP %2d: %s", $_, `ps -aux | grep $$ | grep -v grep` unless $_ % 10; } exit; </snip>
Subject: Proposed patch
From: Christian Borup <borup [...] cpan.org>
I was bitten by this problem also. The attached is a patch against cvs head. It fixes the problem by weakening the reference to self. [SCOTTW - Mon Jul 19 12:07:33 2004]: Show quoted text
> Email::MIME::parts_single_part creates a self-referencing object: > > $self->{parts} = [ $self ]; > > this memory is never freed until the process terminates. For long- > lived processes where Email::MIME is used to parts many messages, the > leak can be significant. > > Here is some code that will output 'ps' for bsd-ish systems: > <snip> > #!/usr/local/bin/perl -w > use strict; > > use Email::MIME; > > for ( 1 .. 1000 ) { > my $msg = <<'_MESSAGE_'; > Date: Mon, 28 Jun 2004 23:22:26 -0600 > From: Scott Wiersdorf <scott@perlcode.org> > To: root@nowhere.tld > Subject: Hokey Pokey > > Everybody do the hokey pokey. > > _MESSAGE_ > > ## this same message parsed with Email::Simple does not leak > Email::MIME->new($msg); ## parse and throw away > printf STDERR "LOOP %2d: %s", $_, `ps -aux | grep $$ | grep -v > grep` > unless $_ % 10; > } > > exit; > </snip>
Index: MIME.pm =================================================================== RCS file: /usr/local/cvs-mailclue-comm/perl/pep/Email-MIME/MIME.pm,v retrieving revision 1.3 diff -u -r1.3 MIME.pm --- MIME.pm 16 Nov 2004 16:35:42 -0000 1.3 +++ MIME.pm 2 Nov 2005 21:35:17 -0000 @@ -5,6 +5,7 @@ require 5.006; use strict; use Carp; +use Scalar::Util qw(weaken); use warnings; our $VERSION = '1.82'; @@ -57,7 +58,8 @@ sub parts_single_part { my $self = shift; - $self->{parts} = [ $self ]; + $self->{parts} = []; + weaken( $self->{parts}->[0]= $self ); return $self; }
From: Marc Beyer <japh [...] tirwhan.org>
I ran into the same problem. Attached is another patch which also fixes the issue by not storing the reference to $self in $self->{parts} but changing parts() to return $self if @{$self->{parts}} is empty. This means it does not require Scalar::Util (BORUPs solution), but it will break any code that tries to use $self->{parts} directly (to which I'd say serves 'em right for not sticking to the API :-). It'd be great to get one of these fixes applied because this bug really hurts.
Index: MIME.pm =================================================================== --- MIME.pm (Revision 1) +++ MIME.pm (Revision 2) @@ -25,7 +25,7 @@ sub parts { my $self = shift; if (!$self->{parts}) { $self->fill_parts } - return @{$self->{parts}} + return scalar @{$self->{parts}} ? @{$self->{parts}} : $self; } sub fill_parts { @@ -57,7 +57,7 @@ sub parts_single_part { my $self = shift; - $self->{parts} = [ $self ]; + $self->{parts} = [ ]; return $self; }
Thanks for the patch, I've applied a modified version of it in Subversion. We can't say: return @parts ? @parts : $self; # more or less because in scalar context $self will be the object, not the count, which means that in numeric scalar context, we'll think we have more than one part! Actually, quite a lot, probably. Anyway, fixing that is simple. The next release of Email-MIME will have this leak dead.
Fixed and released. -- rjbs