[mod_python] stumped by inputfilter infinite repeat

Ken Manheimer ken.manheimer at gmail.com
Mon Aug 20 20:19:21 EDT 2007


On 8/20/07, Graham Dumpleton <graham.dumpleton at gmail.com> wrote:
> On 21/08/07, Ken Manheimer <ken.manheimer at gmail.com> wrote:
> > On 8/18/07, Graham Dumpleton <graham.dumpleton at gmail.com> wrote:
> > > Which version of mod_python and Apache are you using?
> > >
> > > The Tramline author suspected there existed a problem in mod_python
> > > and/or Apache that caused some issues. They suggest in their
> > > documentation a change that should be made to mod_python, although it
> > > hasn't been done in official releases as it wouldn't seem to be the
> > > correct thing to do. One issue was fixed in filter code in mod_python
> > > in recent versions which may have caused issues, but not the same
> > > change they suggested. They also felt that certain older versions of
> > > Apache may have had some problem.
> > >
> > > For some more details see:
> > >
> > >   https://issues.apache.org/jira/browse/MODPYTHON-76
> >
> > thanks much, graham, for your reply.  i did know about the need to
> > inihbit filter.flush() - it's described in the tramline install
> > instructions.  i also factored tramline completely out of the picture,
> > reproducing the behavior using instead some trivial artifical
> > inputfilter and outputfilter functions:
> >
> >   def inputfilter(filter):
> >       "stub input filter"
> >       filter.req.log_error("klm input filter")
> >
> >   def outputfilter(filter):
> >       "stub output filter"
> >       filter.req.log_error("klm output filter")
> >
> > running without pdb enabled but through the rewrite rule i mentioned
> > earlier, to Zope, yields an infinite stream of the "klm input filter"
> > messages, and no "klm output filter" ones.  (the problem does *not*
> > happen when the Zope backend is not running.)
>
> As I would expect, as the input filter is neither consuming the data
> or passing it on. Try something like:
>
> from mod_python import apache
>
> def inputfilter(filter):
>
>     s = filter.read()
>     while s:
>         filter.write(s)
>         s = filter.read()
>
>     if s is None:
>         filter.close()
>
> Similar for output filter.

hmm!

the lack of any input handling in my routine was really dumb.  but in
any case, this may point to something that gets tramline working.

the tramline input filter is intended to only intervene for main POST
requests that consist of multipart/form-data.  for other requests it
would do a filter.pass_on() and return:

    def inputfilter(filter):
        # we're done if we're in a subrequest
        if filter.req.main is not None:
            filter.pass_on()
            return

        # we only handle POST requests
        if filter.req.method != 'POST':
            filter.pass_on()
            return

        # we only handle multipart/form-data
        enctype = filter.req.headers_in.get('Content-Type')
        if enctype[:19] != 'multipart/form-data':
            filter.pass_on()
            return

        [do some real stuff, otherwise]

i the assume that the filter.pass_on() was supposed to do the right
thing, but i tried that in my stub filters (after confirming that your
filter.read()/filter.write() handling did in fact work, graham), and
it didn't.  so i replaced the above with:

    def inputfilter(filter):

        enctype = filter.req.headers_in.get('Content-Type')
        if ((filter.req.main is not None)   # we are in a subrequest
            or (filter.req.method != 'POST')# this is not a POST
request
            or (enctype[:19] != 'multipart/form-data')): # not
multipart/form-data:
            s = filter.read()
            while s:
                filter.write(s)
                s = filter.read()
            if s is None:
                filter.close()
            return

        [do some real stuff, otherwise]

and i don't get the hang.  i have to test the intended tramline
operation, and don't understand enough yet about it or mod_python
filters to be confident that i have something right, but at least i
have something to work with now!

can you say why the filter.pass_on() is not sufficient, by the way?
even with and added filter.flush() the infinite repeat still happens.

> > i did reread the bug report, and it occurred to me to try the current
> > apache svn version, as the bug report mentions - an off chance,
> > though, since the features of the svn version around the time of the
> > bug report should have seen released by now.  unfortunately, that
> > works worse.  i'm getting a fatal error trying to run the latest svn
> > version with mod_python installed:
> >
> > httpd: Syntax error on line 116 of /usr/local/apache2/conf/httpd.conf:
> > Cannot load /usr/local/apache2/modules/mod_python.so into server:
> > /usr/local/apache2/modules/mod_python.so: undefined symbol:
> > ap_requires
> > err 1:  2811  /usr/local/apache2/bin/apachectl configtest
>
> Do you have multiple versions of Apache on your system? This error
> suggest the mod_python source code has been compiled against a
> different version of Apache than you are trying to use it with.

now that i have something to work with using the current apache
version (which i put back in place from a tarball i created before
trying the install of the svn version), i don't need to resolve the
svn version problems.  still, here are the details:

i do have an older installation, but i'm not running it, and i build
(configure) mod_python with the apxs of the new version.  checked that
a bunch of times, and examined config.status, besides.

  ./configure --with-apxs=/usr/local/apache2/bin/apxs
--with-python=/usr/local/bin/python2.4 --with-max-locks=32

i've been running a version of apache2 out of /usr/local/apache2 for a
few months, though with very light use.  i actually deleted the older
apache2 installation before installing the svn checkout one, to avoid
cross-version contamination.

> > this obstacle on obstacle is discouraging.  a google search reveals no
> > other reports of this particular error, and i have no reason to be
> > confident that getting it working would actually improve the original
> > inputfilter problem.  i plan to inquire on the tramline and plone
> > lists for alternatives.  i am interested to hear insights on this, but
> > think i'm better off pursuing other avenues (there's some alpha plone
> > accommodations for blobs in the zodb), and if that works, giving up on
> > mod_python.
> >
> > i did solve one interesting incidental problem along the way, that
> > might be of value to someone else.  when the interminable inputfilter
> > invocation is happening i have to kill apache with a KILL signal (9).
> > doing that lead to mutex leaks, soon leading to apache start failures,
> > with an error_log complaint like this:
> >
> > [Fri Aug 17 12:00:00 2007] [error] (28)No space left on device:
> > mod_python: Failed to create global mutex 0 of 32 (/tmp/mpmtx125450).
>
> You need to make sure you kill off the zombie Apache parent processes
> as well if any exist. It will only be when they have gone that the
> mutexes will be released.

i am usually running apache in non-daemon mode, in order to interact
with the pdb session, when this happens:

  /usr/local/apache2/bin/httpd -k start -X -DONE_PROCESS

^C or default kill signal doesn't kill it.  no other httpd processes
exist.  i don't think the problem is due to running in the foreground,
however - i think the server is blocking on some kind of IO.  it
happens whether or not PythonDebugPdb is set, but it doesn't happen
when i do a regular apachectl start - then killing the lead httpd
processes results in an eventual KILL signal from some supervisor.
the mutex leaks don't happen then.

> > investigating, i learned about ipcs to report semaphores and ipcrm to
> > remove them, and created a little script that did the job for me:
> >
> > ipcs -s | while read key id garbage; do
> >   case "$id" in
> >     [0-9]* ) echo -n "$id "
> >              ipcrm -s $id;;
> >     * ) : ;;
> >   esac
> > done
> >
> > handy.
>