Yes regarding placement of PyThreadState_Clear...sorry about that. I
rebuilt and ran my simple test and it shows no leaks.
static void release_interpreter(void)
{
PyThreadState *tstate = PyThreadState_Get();
// JSR
PyThreadState_Clear(tstate);
#ifdef WITH_THREAD
PyEval_ReleaseThread(tstate);
#else
PyThreadState_Swap(NULL);
#endif
PyThreadState_Delete(tstate);
}
----- Original Message -----
From: "Graham Dumpleton" <[EMAIL PROTECTED]>
To: <python-dev@httpd.apache.org>
Cc: "Jeff Robbins" <[EMAIL PROTECTED]>
Sent: Thursday, October 19, 2006 7:53 AM
Subject: Re: two mod_python leaks
Comments below.
On 19/10/2006, at 8:55 PM, Graham Dumpleton wrote:
For such issues, by all means just send the email direct to the mailing
list.
I have copied this back onto the list and I'll do some research into
what
you describe.
BTW, I don't use Windows, but there are others on the list who do and it
may help if you can explain what methodology you are using to see the
Win32 handle leaks. This will help others to replicate it and then track
it
down.
Thanks.
Graham
On 19/10/2006, at 8:50 PM, Jeff Robbins wrote:
Graham,
I apologize in advance for not understanding the email etiquette for
the list, so I'm emailing you directly. (I subscribed to the
python-dev list and email the faq magic subject but the reply said "no
info".) Anyway...
I know of two leaks in Python 3.2.10 / Apache 2.2.3 that I would dearly
love to get fixed. One of them I have identified the source and made a
change to my copy and it works (and comports with the python embedding
documentation) so I was hoping you could either get it in or help me
understand how I can get it applied.
The first leak is if you use the _repr_ function of a dict or list
(which is as simple as using str([]) in your mod_python handler!) The
repr functions use a dict in the python threadstate to avoid some
recursion problem. This dict is allocated only on demand, so while I
found str([]) (or a str of any dict or list) to cause its allocation,
there may be other user code things you can do to get it allocated. To
free it, the python embedder need to call "PyThreadState_Clear" before
calling "PyThreadState_Delete". Yet mod_python.c release_interpreter()
does not call "PyThreadState_Clear". The fixed version of
release_interpreter is this:
static void release_interpreter(void)
{
PyThreadState *tstate = PyThreadState_Get();
#ifdef WITH_THREAD
PyEval_ReleaseThread(tstate);
#else
PyThreadState_Swap(NULL);
#endif
// JSR
PyThreadState_Clear(tstate);
PyThreadState_Delete(tstate);
}
Still looking at this, but where you do it looks to be wrong. The
documentation
below for PyThreadState_Clear() says:
The interpreter lock must be held.
Where you are calling that function, it isn't. It may need to be moved to
before
the call to PyEval_ReleaseThread(). Yes/No?
The Python embedded doc is clear that this is the correct thing to do:
http://docs.python.org/api/threads.html
...
void PyThreadState_Clear( PyThreadState *tstate)
Reset all information in a thread state object. The interpreter lock
must be held.
void PyThreadState_Delete( PyThreadState *tstate)
Destroy a thread state object. The interpreter lock need not be held.
The thread state must have been reset with a previous call to
PyThreadState_Clear().
Graham
from mod_python import apache
import gc, time
def gccheck():
col = gc.collect()
objects = gc.get_objects()
now = time.asctime()
return len(objects)
c = 0
def handler(req):
global c
global gcc
x = str({'k1':1})
c += 1
req.write('%d\n' % (c % 100))
if c % 100 == 0:
req.write('%d\n' % gccheck())
return apache.OK