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.
$




Reply via email to