On Jan 8, 2007, at 12:42 PM, Nicholas Clark wrote:
On Mon, Jan 08, 2007 at 12:23:09PM -0800, Marvin Humphrey wrote:
Unfortunately, I've never succeeded in banishing all of Perl's leaks
when debugging XS under either 5.8.8 or 5.9.4. Now that we're having
this discussion, I will attempt to write up a test case illustrating
the problem.
Curious. We thought that we'd nailed (most?) every leak in current
blead.
For one of the two issues, the test case can be further reduced down
to this:
$ valgrind --leak-check=full --show-reachable=yes \
> /usr/local/dblead/bin/perl5.9.5 -MCwd -e1
Actually, it doesn't need to be Cwd. Any XS module will do:
Digest::MD5, Fcntl, etc. Each -M directive produces 5 "still
reachable" blocks, so C<valgrind debugperl -MCwd -MFcntl -e1>
produces 10 and so on.
The blocks all originate with DynaLoader::dl_open_file. They can be
eliminated like so:
$ valgrind --leak-check=full --show-reachable=yes \
> /usr/local/dblead/bin/perl5.9.5 -MCwd \
> -e 'DynaLoader::dl_unload_file($_) for @DynaLoader::dl_librefs'
Full output below.
The DynaLoader documentation seems to indicate that Perl should be
cleaning up @dl_librefs automatically:
dl_unload_file()
Syntax:
$status = dl_unload_file($libref)
Dynamically unload $libref, which must be an opaque
'library refer-
ence' as returned from dl_load_file. Returns one on
success and
zero on failure.
This function is optional and may not necessarily be
provided on
all platforms. If it is defined, it is called
automatically when
the interpreter exits for every shared object or library
loaded by
DynaLoader::bootstrap. All such library references are
stored in
@dl_librefs by DynaLoader::Bootstrap as it loads the
libraries.
The files are unloaded in last-in, first-out order.
Looking closer into ext/DynaLoader/dlutils.c, though, I find that
Perl must be compiled with -DDL_UNLOAD_ALL_AT_EXIT to enable the
cleanup.
It seems to me that DynaLoader's docs need to be amended.
Furthermore, I'd like to seek the section about Valgrind in
perlhack.pod amended to include a recommendation about adding -
DDL_UNLOAD_ALL_AT_EXIT. I'll submit a doc patch if people consider
this reasonable.
However, before I do that, I'd like to know whether
DL_UNLOAD_ALL_AT_EXIT should be defined more often. Should DEBUGGING
turn it on? If so then there's no need to patch perlhack. Or should
it be on all the time? IIUC, not cleaning up @dl_librefs will cause
an ongoing leak in situations where multiple Perl interpreters come
and go.
Marvin Humphrey
Rectangular Research
http://www.rectangular.com/
$ valgrind --leak-check=full --show-reachable=yes \
> /usr/local/dblead/bin/perl5.9.5 -MCwd -e1
==7365== Memcheck, a memory error detector.
==7365== Copyright (C) 2002-2005, and GNU GPL'd, by Julian Seward et al.
==7365== Using LibVEX rev 1471, a library for dynamic binary
translation.
==7365== Copyright (C) 2004-2005, and GNU GPL'd, by OpenWorks LLP.
==7365== Using valgrind-3.1.0, a dynamic binary instrumentation
framework.
==7365== Copyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.
==7365== For more details, rerun with: -v
==7365==
==7365==
==7365== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 23 from 1)
==7365== malloc/free: in use at exit: 867 bytes in 5 blocks.
==7365== malloc/free: 11,818 allocs, 11,813 frees, 583,459 bytes
allocated.
==7365== For counts of detected errors, rerun with: -v
==7365== searching for pointers to 5 not-freed blocks.
==7365== checked 256,400 bytes.
==7365==
==7365== 28 bytes in 1 blocks are still reachable in loss record 1 of 5
==7365== at 0x401A619: malloc (vg_replace_malloc.c:149)
==7365== by 0x400B245: _dl_map_object_deps (in /lib/ld-2.3.2.so)
==7365== by 0x41A1DBA: dl_open_worker (in /lib/libc-2.3.2.so)
==7365== by 0x400C265: _dl_catch_error (in /lib/ld-2.3.2.so)
==7365== by 0x41A19AE: _dl_open (in /lib/libc-2.3.2.so)
==7365== by 0x4039F6A: dlopen_doit (in /lib/libdl-2.3.2.so)
==7365== by 0x400C265: _dl_catch_error (in /lib/ld-2.3.2.so)
==7365== by 0x403A315: _dlerror_run (in /lib/libdl-2.3.2.so)
==7365== by 0x4039F13: dlopen@@GLIBC_2.1 (in /lib/libdl-2.3.2.so)
==7365== by 0x8151060: XS_DynaLoader_dl_load_file (DynaLoader.xs:191)
==7365== by 0x80BC573: Perl_pp_entersub (pp_hot.c:2900)
==7365== by 0x80921BE: Perl_runops_debug (dump.c:1898)
==7365==
==7365==
==7365== 61 bytes in 1 blocks are still reachable in loss record 2 of 5
==7365== at 0x401A619: malloc (vg_replace_malloc.c:149)
==7365== by 0x400968D: _dl_new_object (in /lib/ld-2.3.2.so)
==7365== by 0x40055DA: _dl_map_object_from_fd (in /lib/ld-2.3.2.so)
==7365== by 0x400468A: _dl_map_object (in /lib/ld-2.3.2.so)
==7365== by 0x41A1B6A: dl_open_worker (in /lib/libc-2.3.2.so)
==7365== by 0x400C265: _dl_catch_error (in /lib/ld-2.3.2.so)
==7365== by 0x41A19AE: _dl_open (in /lib/libc-2.3.2.so)
==7365== by 0x4039F6A: dlopen_doit (in /lib/libdl-2.3.2.so)
==7365== by 0x400C265: _dl_catch_error (in /lib/ld-2.3.2.so)
==7365== by 0x403A315: _dlerror_run (in /lib/libdl-2.3.2.so)
==7365== by 0x4039F13: dlopen@@GLIBC_2.1 (in /lib/libdl-2.3.2.so)
==7365== by 0x8151060: XS_DynaLoader_dl_load_file (DynaLoader.xs:191)
==7365==
==7365==
==7365== 61 bytes in 1 blocks are still reachable in loss record 3 of 5
==7365== at 0x401A619: malloc (vg_replace_malloc.c:149)
==7365== by 0x4004868: _dl_map_object (in /lib/ld-2.3.2.so)
==7365== by 0x41A1B6A: dl_open_worker (in /lib/libc-2.3.2.so)
==7365== by 0x400C265: _dl_catch_error (in /lib/ld-2.3.2.so)
==7365== by 0x41A19AE: _dl_open (in /lib/libc-2.3.2.so)
==7365== by 0x4039F6A: dlopen_doit (in /lib/libdl-2.3.2.so)
==7365== by 0x400C265: _dl_catch_error (in /lib/ld-2.3.2.so)
==7365== by 0x403A315: _dlerror_run (in /lib/libdl-2.3.2.so)
==7365== by 0x4039F13: dlopen@@GLIBC_2.1 (in /lib/libdl-2.3.2.so)
==7365== by 0x8151060: XS_DynaLoader_dl_load_file (DynaLoader.xs:191)
==7365== by 0x80BC573: Perl_pp_entersub (pp_hot.c:2900)
==7365== by 0x80921BE: Perl_runops_debug (dump.c:1898)
==7365==
==7365==
==7365== 96 bytes in 1 blocks are still reachable in loss record 4 of 5
==7365== at 0x401B8F1: calloc (vg_replace_malloc.c:279)
==7365== by 0x400D035: _dl_check_map_versions (in /lib/ld-2.3.2.so)
==7365== by 0x41A23C8: dl_open_worker (in /lib/libc-2.3.2.so)
==7365== by 0x400C265: _dl_catch_error (in /lib/ld-2.3.2.so)
==7365== by 0x41A19AE: _dl_open (in /lib/libc-2.3.2.so)
==7365== by 0x4039F6A: dlopen_doit (in /lib/libdl-2.3.2.so)
==7365== by 0x400C265: _dl_catch_error (in /lib/ld-2.3.2.so)
==7365== by 0x403A315: _dlerror_run (in /lib/libdl-2.3.2.so)
==7365== by 0x4039F13: dlopen@@GLIBC_2.1 (in /lib/libdl-2.3.2.so)
==7365== by 0x8151060: XS_DynaLoader_dl_load_file (DynaLoader.xs:191)
==7365== by 0x80BC573: Perl_pp_entersub (pp_hot.c:2900)
==7365== by 0x80921BE: Perl_runops_debug (dump.c:1898)
==7365==
==7365==
==7365== 621 bytes in 1 blocks are still reachable in loss record 5 of 5
==7365== at 0x401B8F1: calloc (vg_replace_malloc.c:279)
==7365== by 0x4009472: _dl_new_object (in /lib/ld-2.3.2.so)
==7365== by 0x40055DA: _dl_map_object_from_fd (in /lib/ld-2.3.2.so)
==7365== by 0x400468A: _dl_map_object (in /lib/ld-2.3.2.so)
==7365== by 0x41A1B6A: dl_open_worker (in /lib/libc-2.3.2.so)
==7365== by 0x400C265: _dl_catch_error (in /lib/ld-2.3.2.so)
==7365== by 0x41A19AE: _dl_open (in /lib/libc-2.3.2.so)
==7365== by 0x4039F6A: dlopen_doit (in /lib/libdl-2.3.2.so)
==7365== by 0x400C265: _dl_catch_error (in /lib/ld-2.3.2.so)
==7365== by 0x403A315: _dlerror_run (in /lib/libdl-2.3.2.so)
==7365== by 0x4039F13: dlopen@@GLIBC_2.1 (in /lib/libdl-2.3.2.so)
==7365== by 0x8151060: XS_DynaLoader_dl_load_file (DynaLoader.xs:191)
==7365==
==7365== LEAK SUMMARY:
==7365== definitely lost: 0 bytes in 0 blocks.
==7365== possibly lost: 0 bytes in 0 blocks.
==7365== still reachable: 867 bytes in 5 blocks.
==7365== suppressed: 0 bytes in 0 blocks.
$
$ valgrind --leak-check=full --show-reachable=yes \
> /usr/local/dblead/bin/perl5.9.5 -MCwd \
> -e 'DynaLoader::dl_unload_file($_) for @DynaLoader::dl_librefs'
==7368== Memcheck, a memory error detector.
==7368== Copyright (C) 2002-2005, and GNU GPL'd, by Julian Seward et al.
==7368== Using LibVEX rev 1471, a library for dynamic binary
translation.
==7368== Copyright (C) 2004-2005, and GNU GPL'd, by OpenWorks LLP.
==7368== Using valgrind-3.1.0, a dynamic binary instrumentation
framework.
==7368== Copyright (C) 2000-2005, and GNU GPL'd, by Julian Seward et al.
==7368== For more details, rerun with: -v
==7368==
==7368==
==7368== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 23 from 1)
==7368== malloc/free: in use at exit: 0 bytes in 0 blocks.
==7368== malloc/free: 11,845 allocs, 11,845 frees, 584,191 bytes
allocated.
==7368== For counts of detected errors, rerun with: -v
==7368== No malloc'd blocks -- no leaks are possible.
$