Graham Dumpleton wrote ..
> Extending the above code as:
> 
>     Py_BEGIN_ALLOW_THREADS;
>     rc = ap_get_brigade(c->input_filters, bb, mode, APR_BLOCK_READ, bufsize);
>     Py_END_ALLOW_THREADS;
> 
>     if (! APR_STATUS_IS_SUCCESS(rc)) {
>         PyErr_SetObject(PyExc_IOError,
>                         PyString_FromString("Connection read error"));
>         return NULL;
>     }
> 
>     /* Return empty string if no buckets. Can be caused by EAGAIN. */
>     if (APR_BRIGADE_EMPTY(bb)) {
>         return PyString_FromString("");
>     }
> 
> seems to fix the problem. Ie., use call to APR_BRIGADE_EMPTY(bb) to check
> whether any new buckets added and returning empty string if not.

Okay, this may work, but the EAGAIN propogating backup as an empty
string to Python can cause a tight loop to occur where calls are going
out and back into Python code. This will occur until something is read
or an error occurs.

To avoid the back and forth, another option may be:

    while (APR_BRIGADE_EMPTY(bb)) {
        Py_BEGIN_ALLOW_THREADS;
        rc = ap_get_brigade(c->input_filters, bb, mode, APR_BLOCK_READ, 
bufsize);
        Py_END_ALLOW_THREADS;

        if (! APR_STATUS_IS_SUCCESS(rc)) {
            PyErr_SetObject(PyExc_IOError,
                            PyString_FromString("Connection read error"));
            return NULL;
        }
    }

What doesn't make sense to me is that on my Mac OS X box where this
problem only occurs when you have two listener ports, even when you
have already read some input from the connection, it tight loops with
the lowest level read always returning EAGAIN. Ie., it doesn't block at all.

Thus something really bad is happening on on Mac OS X. Unless Apache
is setting some strange ioctl options on the socket to inadvertently
cause this, it looks to me like Mac OS X is broken in some way. I am
still on Mac OS X (10.3). I'll have to try it on my 10.4 box and see if it
makes any difference.

Graham

Reply via email to