[Zope-dev] Zope closes connection if the client closes the write-end of connection
Tres Seaver
tseaver at palladion.com
Fri Oct 16 10:36:34 EDT 2009
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Izak Burger wrote:
> Hi again,
>
> Izak Burger wrote:
>> I eventually distilled the check varnish uses into a small C program,
>> and an interesting problem shows up. When you call shutdown(fd, SHUT_WR)
>> on your socket connection, in effect telling zope that you're done
>> talking to it, it looks like zope responds in kind by not talking to you
>> either. I deduce this from the fact that poll() returns POLLHUP in
>> revents and read() returns zero (EOF). POLLHUP, if I understand this
>> correctly, means the other side (zope) has hung up.
>
> It seems this might not be a bug in zope. I'd like to describe what I've
> found this morning and where this is most possibly going wrong. Please
> tell me if I'm mistaken about something.
>
> This goes all the way to what happens when you call poll() on a file
> descriptor. If you ask to be notified for POLLIN events only, it does
> not necessarily guarantee that POLLIN (or a timeout) are the only events
> that can cause poll() to return. The man page does not properly document
> this, but the header file does:
>
> /* Event types always implicitly polled for. These bits need not be set
> in `events', but they will appear in `revents' to indicate the status
> of the file descriptor. */
> #define POLLERR 0x008 /* Error condition. */
> #define POLLHUP 0x010 /* Hung up. */
> #define POLLNVAL 0x020 /* Invalid polling request. */
>
> In other words, a POLLHUP event can cause your poll() call to return
> even though the POLLIN event you were looking for didn't occur.
>
> If we inspect Modules/socketmodule.c in the python (2.4.4) source code
> we see that it is assumed that if poll() returns a value greater than
> zero, it means data is available for reading.
>
> If the client calls shutdown(SHUT_WR), this will cause a POLLHUP, which
> fools python into thinking there is data to be read. When it attempts to
> read that data, it ends up with nothing, that is, recv() returns 0.
>
> Moving on to asyncore.py, we see this:
>
> data = self.socket.recv(buffer_size)
> if not data:
> # a closed connection is indicated by signaling
> # a read condition, and having recv() return 0.
> self.handle_close()
> return ''
>
> And handle_close eventually ends up telling zope to close the connection.
>
> This has two possible fixes, but both are probably required. Firstly, it
> seems the latest python still has this problem, so I probably need to
> report it as a bug. Secondly, since zope still requires older python
> versions to run, a workaround probably needs to be found. I suppose just
> rebuilding the _socket native module will probably do it and I will test
> this as soon as I have more time.
You might also look at "fixing" varnish: I don't know of any valid
reason for it to be using the "half-open" connection model to test that
an HTTP-based backend is "up" -- certainly no browser in the world does
that; instead, modern browsers nearly always try to keep the connection
open for subsequent requests.
Tres.
- -- ~~
===================================================================
Tres Seaver +1 540-429-0999 tseaver at palladion.com
Palladion Software "Excellence by Design" http://palladion.com
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org
iEYEARECAAYFAkrYhPIACgkQ+gerLs4ltQ5PpACg19JYJc7pTUiUMZV8IWnGi5Dv
tJMAnikqfgLsi4lZB1eerO01d/48w3SK
=5mP5
-----END PGP SIGNATURE-----
More information about the Zope-Dev
mailing list