[Python-Dev] Internal counter to debug leaking file descriptors
David Malcolm
dmalcolm at redhat.com
Tue Aug 31 20:39:52 CEST 2010
On Tue, 2010-08-31 at 17:40 +0000, exarkun at twistedmatrix.com wrote:
> On 05:22 pm, glyph at twistedmatrix.com wrote:
> >
> >On Aug 31, 2010, at 10:03 AM, Guido van Rossum wrote:
> >>On Linux you can look somewhere in /proc, but I don't know that it
> >>would help you find where a file was opened.
> >
> >"/dev/fd" is actually a somewhat portable way of getting this
> >information. I don't think it's part of a standard, but on Linux it's
> >usually a symlink to "/proc/self/fd", and it's available on MacOS and
> >most BSDs (based on a hasty and completely-not-comprehensive
> >investigation). But it won't help you find out when the FDs were
> >originally opened, no.
> >_______________________________________________
>
> On OS X and Solaris, dtrace and ustack will tell you exactly when and
> where the FDs were originally opened, though. On Linux, SystemTap might
> give you the same information (but I know much less about SystemTap).
> If http://bugs.python.org/issue4111 is resolved, then this may even be
> possible without using a patched version of Python.
I believe you can do something like this:
$ cat /tmp/trace-all-syscalls.stp
/*
Watch all syscalls in a specified process, dumping a user-space
backtrace
*/
probe syscall.* {
if (pid() == target()) {
printf("%s(%s)\n", probefunc(), argstr)
print_ubacktrace();
}
}
$ sudo stap --ldd -d /usr/bin/python /tmp/trace-all-syscalls.stp -c "python -c 'print 42'"
This generates a torrent of debug data like this:
sys_mmap_pgoff(0x0, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
0x38f44e17aa : mmap64+0xa/0x30 [libc-2.11.90.so]
0x38f44673fc : _IO_file_doallocate+0x7c/0x110 [libc-2.11.90.so]
0x38f447498c : _IO_doallocbuf+0x2c/0x50 [libc-2.11.90.so]
0x38f4472ef4 : _IO_file_underflow@@GLIBC_2.2.5+0x1b4/0x230 [libc-2.11.90.so]
0x38f44749ce : _IO_default_uflow+0xe/0x30 [libc-2.11.90.so]
0x38f446fdcb : getc+0xab/0xf0 [libc-2.11.90.so]
0x39054f3e13 : r_long+0x23/0x120 [libpython2.6.so.1.0]
0x39054f3f3b : PyMarshal_ReadLongFromFile+0x2b/0x30 [libpython2.6.so.1.0]
0x39054f0661 : load_source_module+0x271/0x640 [libpython2.6.so.1.0]
0x39054f1cc5 : import_submodule+0x155/0x300 [libpython2.6.so.1.0]
0x39054f1f85 : load_next+0x115/0x2a0 [libpython2.6.so.1.0]
0x39054f2592 : import_module_level+0x212/0x730 [libpython2.6.so.1.0]
0x39054f3314 : PyImport_ImportModuleLevel+0x44/0xb0 [libpython2.6.so.1.0]
0x39054d843f : builtin___import__+0x8f/0xa0 [libpython2.6.so.1.0]
0x3905443f43 : PyObject_Call+0x53/0x100 [libpython2.6.so.1.0]
0x39054d89b3 : PyEval_CallObjectWithKeywords+0x43/0xf0 [libpython2.6.so.1.0]
0x39054db674 : PyEval_EvalFrameEx+0x21b4/0x65b0 [libpython2.6.so.1.0]
0x39054e03a8 : PyEval_EvalCodeEx+0x938/0x9e0 [libpython2.6.so.1.0]
0x39054e0482 : PyEval_EvalCode+0x32/0x40 [libpython2.6.so.1.0]
0x39054f02c2 : PyImport_ExecCodeModuleEx+0xc2/0x1f0 [libpython2.6.so.1.0]
0x39054f07a6 : load_source_module+0x3b6/0x640 [libpython2.6.so.1.0]
You may want to specify specific syscalls in the above to narrow the
scope.
Issue 4111 patches cpython to statically mark Python frame entry/exit so
that systemtap can directly instrument that; in Fedora 13 onwards I've
built Python with systemtap hooks so that you can add:
probe python.function.entry {
printf("%s:%s:%d\n", filename, funcname, lineno);
}
(Arguably this is wrong, it's frame entry/exit, rather than function
entry/exit).
Potentially systemtap could be taught how to decipher/prettyprint Python
backtraces in a similar way to how gdb does it (by hooking into
PyEval_EvalFrameEx)
Hope this is helpful
Dave
More information about the Python-Dev
mailing list