Bug#823409: proftpd RMemoryLimit large file transfer fails ( possible memory leak )
Daniel Swarbrick
daniel.swarbrick at profitbricks.com
Thu Dec 1 13:09:01 UTC 2016
We are also seeing what appears to be a memory leak, which becomes quite
a problem when users upload large files. We are _not_ using RMemoryLimit.
On one of our FTP servers, a user is currently uploading a large file,
430 GB so far, and the proftpd process has used almost 10 GB of memory.
It seems to be concentrated in a single large allocation, according to pmap:
$ sudo pmap 54962 | grep anon
00000000006cb000 48K rw--- [ anon ]
00000000009fc000 720K rw--- [ anon ]
0000000000ab0000 4K rw--- [ anon ]
0000000000ab1000 4K rw--- [ anon ]
0000000000ab2000 4K rw--- [ anon ]
0000000000ab3000 56K rw--- [ anon ]
0000000000ac1000 9698984K rw--- [ anon ]
00007f3232069000 4K rw--- [ anon ]
00007f3232acb000 4K rw--- [ anon ]
00007f3232ffb000 8K rw--- [ anon ]
00007f3234d68000 16K rw--- [ anon ]
00007f32361de000 8K rw--- [ anon ]
00007f32363ed000 4K rw--- [ anon ]
00007f3237681000 8K rw--- [ anon ]
00007f3237fb0000 8K rw--- [ anon ]
00007f32381cf000 40K rw--- [ anon ]
00007f32389f1000 84K rw--- [ anon ]
00007f3238e44000 16K rw--- [ anon ]
00007f32393fa000 16K rw--- [ anon ]
00007f323a25c000 12K rw--- [ anon ]
00007f323a4c3000 4K rw--- [ anon ]
00007f323ad5c000 184K rw--- [ anon ]
00007f323af99000 40K rw--- [ anon ]
00007f323afa7000 16K rw--- [ anon ]
00007f323afad000 8K rw--- [ anon ]
00007fff913c3000 8K r---- [ anon ]
00007fff913c5000 8K r-x-- [ anon ]
ffffffffff600000 4K r-x-- [ anon ]
Digging though the proftpd source code a bit, I see that it implements
memory pools, so this single large allocation may consist of multiple
smaller buffers. I also ran an strace on the process, and can see it
making brk() syscalls every few seconds (i.e., malloc / realloc and
friends).
$ sudo strace -r -e trace=memory -p 54962
Process 54962 attached
0.000000 brk(0x204b9b000) = 0x204b9b000
8.002960 brk(0x204bbc000) = 0x204bbc000
3.572409 brk(0x204bdd000) = 0x204bdd000
2.019134 brk(0x204bfe000) = 0x204bfe000
3.794139 brk(0x204c1f000) = 0x204c1f000
0.934894 brk(0x204c40000) = 0x204c40000
7.322138 brk(0x204c61000) = 0x204c61000
8.286779 brk(0x204c82000) = 0x204c82000
8.196694 brk(0x204ca3000) = 0x204ca3000
8.105567 brk(0x204cc4000) = 0x204cc4000
8.548908 brk(0x204ce5000) = 0x204ce5000
8.066531 brk(0x204d06000) = 0x204d06000
8.020094 brk(0x204d27000) = 0x204d27000
7.149787 brk(0x204d48000) = 0x204d48000
7.566161 brk(0x204d69000) = 0x204d69000
2.763174 brk(0x204d8a000) = 0x204d8a000
5.481161 brk(0x204dab000) = 0x204dab000
7.637086 brk(0x204dcc000) = 0x204dcc000
2.111138 brk(0x204ded000) = 0x204ded000
5.650550 brk(0x204e0e000) = 0x204e0e000
6.037580 brk(0x204e2f000) = 0x204e2f000
6.959830 brk(0x204e50000) = 0x204e50000
7.927986 brk(0x204e71000) = 0x204e71000
^CProcess 54962 detached
Each time the delta is 135168 bytes, which is exactly 132 KiB. A
slightly more detailed strace shows the brk() always occurring after a
socket read (which lsof showed was the data connection socket):
0.000027 write(16, "mZ\373G\266\270\271k\205\236(\242\206\3362\204\261\16\371g\\\256\24\22\334\237L\326\207\206\26\362"..., 4380) = 4380
0.000042 select(1, [0], [], NULL, {0, 0}) = 0 (Timeout)
0.000032 select(19, [18], [], NULL, {1, 0}) = 1 (in [18], left {0, 999998})
0.000039 read(18, "\31\274B\270\373\215\345\364\30\357[\37\n\276\33j\177\32|}\246\370wA\263k\255KR\223d1"..., 87380) = 2920
0.000047 brk(0x207ee9000) = 0x207ee9000
It looks very much like proftpd is allocating some kind of socket receive buffer, and forgetting to free it.
More information about the Pkg-proftpd-maintainers
mailing list