Saju Pillai wrote:
Frank Meier wrote:
Hi
I'm working with a proprietary apache module which communicates (through
a socket) with another backend application (I have the C source code of
the module). I've now found out, when the client closes the http
connection during a request, the module does not "see" that the client
has disconnected. In some cases the request is just finished, but with
larger requests (larger amount of data from backend), the module
keeps hanging in the ap_rwrite() or ap_rflush() function. This is
only resolved if a timeout (default 300s, timeout directive in
httpd.conf) occurs. I think the tx-buffer of the socket is filled and
then the
write/flush function blocks.
I think if the client has gone away while httpd is trying to write()
to it, httpd will immediately error out - probably with a "Broken
Pipe" error.
Even if your socket write buffer is filled, the actual attempt to
write() by your tcp stack must raise an error.
Maybe I am not understanding the problem properly. If the tcp
connection is broken, attempts to read() or write() on that connection
should flag a detectable error. It maybe possible that httpd is
waiting too long to perform a write() and doesn't figure out fast
enough that the remote end has gone away.
I can think of a *hack* to determine if the client has really gone away.
In your module you can possibly do
client = ap_filter_t->ctx->client_socket /* ap_filter_t is either the
input or output filter stack */
to get the apr client socket. You can try do a 0-byte read() on this
socket to see if you get an error. An error means the remote side has
gone away. I have not tested this, I don't know if this will work for
you.
srp
thanks for your replies, I tried the use of bucketbrigades as Chris
Kukuchka suggested. Unfortunately this lead to the same behaviour.
I also tried the *hack* approach (accessing the socket directly), where
I had the problem of getting to the socket itself. I didn't understand
how I could use ap_filter_t->ctx since I don't know what is stored
there, but I used "ap_get_module_config" which should also get me to the
socket. right?
struct apr_socket_t *client_socket =
ap_get_module_config(r->connection->conn_config, &core_module);
int rv = read(client_socket->socketdes, dummyBuf, len);
but rv is always 0 (if len is 0) / -1 (if len > 0) and errno is 2 (No
such file or directory)
> I think if the client has gone away while httpd is trying to write()
to it, httpd will immediately error out - probably with a "Broken Pipe"
error.
that IS what I ought to think too :-)
I think my next step is to implement a test module myself to verify this
strange behaviour and also test it on another OS (linux) since Solaris
sometimes does strange things.
thanks anyway, Frank