Re: FCGI/perl memory leakage

Stanley Gambarin (gambarin@OpenMarket.com)
Fri, 04 Apr 1997 15:05:01 -0500

Message-Id: <199704042005.PAA03861@u4-138.openmarket.com>
To: skimo@breughel.ufsia.ac.be (Sven Verdoolaege)
Subject: Re: FCGI/perl memory leakage 
In-Reply-To: Your message of "Wed, 02 Apr 1997 15:03:53 +0200."
             <19970402150353.DV39224@breughel.ufsia.ac.be> 
Date: Fri, 04 Apr 1997 15:05:01 -0500
From: Stanley Gambarin <gambarin@OpenMarket.com>

> On Apr 1, skimo@breughel.ufsia.ac.be (Sven Verdoolaege) wrote:
> ...
> I think I've located the problem.
> perl is trying to be smart and postpones the desruction of hash elements
> till ... never in this case.
> Quick solution is to uncomment the hv_delete in line 172 of FCGI.xs .
> This may have unwanted side effects.
> Complete solution will take some more time and someone (Stanley ?)
> to explain to me what all this environment stuff is supposed to do.
> 
	Ok, I have looked at the code and i think i have an idea
of what is happening, so I will try to explain:
	- once the request is recieved, we call accept() function
in FCGI.xs.  Each request has an environment stuff that is associated 
with it, which is passed via -initial-env in AppClass for Apache. 
The per request environment is stored in the requestEnvrion, so 
the following code is inside the accept():

	savedEnviron = environ;
        acceptStatus = FCGI_Accept();
        requestEnviron = environ;
        environ = savedEnviron;
   
	These manipulations are done since FCGI_Accept() modifies the 
global environ, but we need to save it for later uses.  So, after we 
got our new environment, we have to set it up by calling
DoPerlEnv(requestEnviron, TRUE);  Finally, at the top, we call the 
DoPerlEnv(requestEnviron, FALSE) to disable the request environment from
the previous request.  If you follow the above suggestion and remove call
to hv_delete() in DoPerlEnv, then if you have 2 requests for the same 
fastcgi app with different environments, then the second request will also
get the environment of the first request, which is a no-no :0.

	The problem with hv_delete() as was correctly stated is that 
the elements are marked for deletion, but the memory is never actually 
freed up.  (in hv.c:hv_delete() you can see the element gets marked
for lazy deletion, but not hv_free()d).  I guess the proper way to 
handle it is to invoke immediate purge of the array, however, I am
not very familiar with Perl API, so I am at loss on how to do it.
Another alternative, which I think would be easier to implement is as 
follows, in DoPerlEnv:
	hv = perl_get_hv("ENV", TRUE);
	backup = HV_copy?(hv);    /* save existing Perl environment */
	if (set==TRUE) then proceed as before.
	if (set==FALSE) /* need to remove the elements */
	delete_hv(hv);  /* remove it completely.. should free memory */
	hv = HV_copy?(backup);    /* copy back the initial values */

	Like I said before, I am not very familiar with the Perl's insides,
so if you (Sven) can find the solution to the above and then email it to me.

						Hope that was of some help.
								Stanley.