On Tuesday, February 3, 2015 at 3:17:37 PM UTC+1, Amirouche Boubekki wrote:
> What you want is to prevent the socket to wait indefinetly for data (based on 
> strace output) which is done with socket.setblocking/settimeout [1]. 
> asynchronous (asyncio) is something else, and you would still need to handle 
> blocking I think.

I have installed Faulthandler, a beautiful tool written by Victor "Haypo" 
Stinner, and thanks to it I could determine precisely where the program hangs. 
It is in ssl.py::SSLSocket::read


    def read(self, len=1024):

        """Read up to LEN bytes and return them.                                
                                                                                
                                                                 
        Return zero-length string on EOF."""

        try:
>            return self._sslobj.read(len) >*< python hangs on this line 
        except SSLError, x:
            if x.args[0] == SSL_ERROR_EOF and self.suppress_ragged_eofs:
                return ''
            else:
                raise

>From the traceback given by faulthandler it seems to me that the problem isn't 
>from my webserver trying to receive connections from clients, but from my 
>server (acting as a client) trying a request on a distant server (https URL -> 
>use of ssl.py). Here's the traceback : 

     1  Current thread 0x00007fb9cb41f700 (most recent call first):
     2  File "/usr/lib/python2.7/ssl.py", line 160 in read
     3  File "/usr/lib/python2.7/ssl.py", line 241 in recv
     4  File "/usr/lib/python2.7/socket.py", line 447 in readline
     5  File "/usr/lib/python2.7/httplib.py", line 365 in _read_status
     6  File "/usr/lib/python2.7/httplib.py", line 407 in begin
     7  File "/usr/lib/python2.7/httplib.py", line 1034 in getresponse
     8  File 
"/usr/local/lib/python2.7/dist-packages/requests/packages/urllib3/connectionpool.py",
 line 353 in _make_request
     9  File 
"/usr/local/lib/python2.7/dist-packages/requests/packages/urllib3/connectionpool.py",
 line 518 in urlopen
    10  File "/usr/local/lib/python2.7/dist-packages/requests/adapters.py", 
line 370 in send
    11  File "/usr/local/lib/python2.7/dist-packages/requests/sessions.py", 
line 573 in send
    12  File "/usr/local/lib/python2.7/dist-packages/requests/sessions.py", 
line 461 in request
    13  File "/usr/local/lib/python2.7/dist-packages/requests/sessions.py", 
line 473 in get
    14  File "/usr/local/lib/python2.7/dist-packages/infomaniak/infomaniak.py", 
line 29 in getFlux
    15  File "/usr/local/lib/python2.7/dist-packages/infomaniak/server.py", 
line 52 in do_GET
    16  File "/usr/lib/python2.7/BaseHTTPServer.py", line 328 in 
handle_one_request
    17  File "/usr/lib/python2.7/BaseHTTPServer.py", line 340 in handle
    18  File "/usr/lib/python2.7/SocketServer.py", line 649 in __init__
    19  File "/usr/lib/python2.7/SocketServer.py", line 334 in finish_request
    20  File "/usr/lib/python2.7/SocketServer.py", line 321 in process_request
    21  File "/usr/lib/python2.7/SocketServer.py", line 295 in 
_handle_request_noblock
    22  File "/usr/lib/python2.7/SocketServer.py", line 238 in serve_forever
    23  File "/usr/local/lib/python2.7/dist-packages/infomaniak/server.py", 
line 71 in <module>
    24  File "/usr/bin/infomaniak", line 2 in <module>
    25   

If you look at line 13, it shows that the server is actually doing a get to an 
external URL via the requests library, which is itself relying on urllib3, 
which in turn is using httplib.py

Below is the code of the last three functions to have been called, in 
chronoligical order : 

In socket.py::_fileobject::readline
           [...]
            while True:
                try:
                    data = self._sock.recv(self._rbufsize) #<------------
                except error, e:
                    if e.args[0] == EINTR:
                        continue
                    raise
                if not data:
                    break
                nl = data.find('\n')
                if nl >= 0:
                    nl += 1
                    buf.write(data[:nl])
                    self._rbuf.write(data[nl:])
                    del data
                    break
                buf.write(data)
            return buf.getvalue()
           [...]

In ssl.py::SSLSocket::recv 

    def recv(self, buflen=1024, flags=0):
        if self._sslobj:
            if flags != 0:
                raise ValueError(
                    "non-zero flags not allowed in calls to recv() on %s" %
                    self.__class__)
            return self.read(buflen)                                  #<-------
        else:
            return self._sock.recv(buflen, flags)


In ssl.py::SSLSocket::read

    def read(self, len=1024):

        """Read up to LEN bytes and return them.                                
                                                                                
                                                                 
        Return zero-length string on EOF."""

        try:
            return self._sslobj.read(len) # >*< python hangs on this line 
        except SSLError, x:
            if x.args[0] == SSL_ERROR_EOF and self.suppress_ragged_eofs:
                return ''
            else:
                raise

I can't go any further because the _sslobj is create via the _ssl.so library, 
it is very likely C code.

Do you have any idea about how I can investigate this any further ?
-- 
https://mail.python.org/mailman/listinfo/python-list

Reply via email to