I noticed that lines 789-793 (in the original file, $Id: requestobject.c 420297) should be moved up to line 780,

  765      if (self->rbuff_pos < self->rbuff_len) {
766 767 /* if yes, process that first */
  768          while (self->rbuff_pos < self->rbuff_len) {
  769
  770              buffer[copied++] = self->rbuff[self->rbuff_pos];
  771              if ((self->rbuff[self->rbuff_pos++] == '\n') ||
  772                  (copied == len)) {
  773
  774                  /* our work is done */
  775
  776                  /* resize if necessary */
  777                  if (copied < len)
  778                      if(_PyString_Resize(&result, copied))
  779                          return NULL;
  780
  781                  return result;
  782              }
  783          }
  784      }

So it should look like this:

   if (self->rbuff_pos < self->rbuff_len) {
/* if yes, process that first */
       while (self->rbuff_pos < self->rbuff_len) {

           buffer[copied++] = self->rbuff[self->rbuff_pos];
           if ((self->rbuff[self->rbuff_pos++] == '\n') ||
               (copied == len)) {

               /* our work is done */

               /* resize if necessary */
               if (copied < len)
                   if(_PyString_Resize(&result, copied))
                       return NULL;

if (self->rbuff_pos >= self->rbuff_len && self->rbuff != NULL) { // dispose of buffer since we no longer need it
                   free(self->rbuff);
                   self->rbuff = NULL;
} return result;
           }
       }
   }

The reason is that we are returning results, line 781 (original file), as the last time that we will ever read from buffer without deallocating the buffer memory.

Even with this fix, which I'm not 100% sure that is a fix, memory still leaking but in a lower rate.

Any help will be greatly appreciated.

/amn
Alexis Marrero wrote:
Experimenting on this issue, I noticed that neither of the following set of "ifs" are ever met:


786 /* Free old rbuff as the old contents have been copied over and 787 we are about to allocate a new rbuff. Perhaps this could be reused
   788         somehow? */
789 if (self->rbuff_pos >= self->rbuff_len && self->rbuff != NULL)
   790      {
   791          free(self->rbuff);
   792          self->rbuff = NULL;
   793      }


--------

   846      /* Free rbuff if we're done with it */
847 if (self->rbuff_pos >= self->rbuff_len && self->rbuff != NULL)
   848      {
   849          free(self->rbuff);
   850          self->rbuff = NULL;
   851      }

I noticed that by putting some statements to write to the output stream. They never execute.

/amn

On Aug 10, 2006, at 1:43 PM, Alexis Marrero wrote:

All,

We are trying to nail down a memory leak that happens only when documents are POSTed to the server.

For testing we have a short script that does:

while True:
    dictionary_of_parameters = {'field1': 'a'*100000}
    post('url...', dictionary_of_parameters)

Then we run "top" on the server and watch the server memory grow without bound. Why do we know that the problem is in request.readline()? If I go to mod_python.util.FieldStorage.read_to_boundary() and add the following statement:

def read_to_boundary(...):
  return True
  ...

as the first executable line in the function the memory does not grow.

I have read the req_readline a 1000 time and I can't figure out where the problem is.


My config:
Python 2.4.1
mod_python 3.2.10

Our request handler does nothing other than using util.FieldStorage(req) and req.write('hello').

I have some suspicion that it has to do with:
....
    19   * requestobject.c
    20   *
    21   * $Id: requestobject.c 420297 2006-07-09 13:53:06Z nlehuen $
    22   *
    23   */
....
   846      /* Free rbuff if we're done with it */
847 if (self->rbuff_pos >= self->rbuff_len && self->rbuff != NULL)
   848      {
   849          free(self->rbuff);
   850          self->rbuff = NULL;
   851      }
   852

Though, I can't confirm.


/amn



Reply via email to