AnsweredAssumed Answered

lighttpd memory leak

Question asked by sonic Employee on Mar 31, 2013
Latest reply on Apr 1, 2013 by mhammons

From Marc <mhammons AT currentgrid DOT com>



I may have the source of this leak, realted to mod_cgi and the bfin port. 

Generally the port to bfin manipulates the mmap() calls and replace fork() with
vfork() which yields a functioning CGI.

However in mod_cgi.c function cgi_create_env() there is a period between the
now vfork() and the execve() where the CGI environment is set up.  After
calling vfork() the parent process is suspended, waiting on the child to exec
or exit, meanwhile the child is sharing the address space of the parent.

In setting up the CGI environment the child performs several calls to
cgi_env_add() which in turn calls malloc(), all prior to the execve().
These malloc() calls serve to setup the environment vector to pass to the
child via the execve() call, but once invoked the malloced memory serving as
the vector contents are leaked into the parent process' address space.  As
written, mod_cgi.c contains no code to recover the contents of the leaked
environment vector within the parent process (it wasn't written with the bfin
in mind).  As the parent lighttpd process is typically a permanent fixture,
over time these leaks contribute to memory leaks and issues, particualrly if
the device has a high-touch UI.  ADI references regarding porting of
applications warn of this type of problem.

Anecdotatly, monitoring the lighttpd process' maps under /proc/<pid>/maps while
repeatedly accessing a UI implemented via lighttpd and mod_cgi will reveal that
over time memory segments are continually being consumed by lighttpd.
Correcting the issue by freeing up the CGI environment from within the parent
process following the execve() seems to result in a stable lighttpd whose
memory consumption does not continually grow with usage.

I've attached a patch to illustrate against lighttpd 1.4.29.  The patch moves moves
the env structure into the pre-vfork() common code and then checks the status of
that structure post vfork() in the parent code branch.  If there is an env structure then
it and its elements are free()d within the parent code branch.  This seems
to have elimintated the memory leaks on our target system.