[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