Subject: | Memory leak using XMLin with a file path as parameter |
In a long-running perl script of ours we noticed that the perl process uses more and more memory the longer the script runs. I've been able to track down the problem to the parsing of an XML
file. The following script reproduces the problem for me on 'v5.8.8 built for x86_64-linux'. The input file's contents are irrelevant.
#!/usr/bin/perl -w
use strict;
use Devel::Mallinfo ('mallinfo');
use XML::Simple;
my $config = "config.xml";
my $previous_memory = mallinfo()->{'uordblks'};
while (1)
{
my $xml = XMLin( $config );
my $h = mallinfo();
my $current_memory = $h->{'uordblks'};
my $diff = $current_memory - $previous_memory;
print("Current memory usage: $current_memory ($diff)\n");
$previous_memory = $current_memory;
sleep(1);
}
#####
Executing this script yields the following results:
# ./xmlmemleak.pl
Current memory usage: 6844320 (5564224)
Current memory usage: 6853264 (8944)
Current memory usage: 6853568 (304)
Current memory usage: 6853824 (256)
Current memory usage: 6854096 (272)
Current memory usage: 6854352 (256)
Current memory usage: 6854624 (272)
The number in parentheses represents the change in bytes in relation to the previous iteration. Positive values stand for increased memory allocation.
I think the problem lies in LibXML.xs in the function '_parse_sax_file' (which is called in my test case, as it seems). The culprit is imho the following snippet:
ctxt->sax = PSaxGetHandler();
PmmSAXInitContext( ctxt, self, saved_error );
Looking at PmmSAXInitContext I can see that ctxt->sax is set in there too (using PSaxGetHandler again), so I think the value set in _parse_sax_file is simply overwritten without being freed.
If I recompile the module with the 'ctxt->sax = ...' line removed from _parse_sax_file(), the leak seems to be gone:
# ./xmlmemleak.pl
Current memory usage: 6843872 (5563600)
Current memory usage: 6852544 (8672)
Current memory usage: 6852544 (0)
Current memory usage: 6852544 (0)
Current memory usage: 6852624 (80)
Current memory usage: 6852544 (-80)
Current memory usage: 6852528 (-16)
Current memory usage: 6852544 (16)
I haven't provided a patch because I'm not sure that my five minutes of looking at the source are enough to guarantee that I don't break other stuff :-)