Uploaded image for project: 'Python Driver'
  1. Python Driver
  2. PYTHON-482

Sockets sometimes lockup for 10mins+

    • Type: Icon: Bug Bug
    • Resolution: Done
    • Priority: Icon: Major - P3 Major - P3
    • None
    • Affects Version/s: 2.4.2
    • Component/s: None
    • None

      I'm frequently seeing PyMongo lockup in a socket receive on a test server with a local mongos:

      self = Database(MongoClient(['cn14:27119', 'localhost:27119']), u'mongoose')
      
          def collection_names(self):
              """Get a list of all the collection names in this database.
                  """
              results = self["system.namespaces"].find(_must_use_master=True)
      >       names = [r["name"] for r in results]
      
      /users/is/ahlpypi/egg_cache/p/pymongo-2.4.2-py2.6-linux-x86_64.egg/pymongo/database.py:403: 
      _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
      
      self = <pymongo.cursor.Cursor object at 0x862c790>
      
          def next(self):
              if self.__empty:
                  raise StopIteration
              db = self.__collection.database
      >       if len(self.__data) or self._refresh():
      
      /users/is/ahlpypi/egg_cache/p/pymongo-2.4.2-py2.6-linux-x86_64.egg/pymongo/cursor.py:814: 
      _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
      
      self = <pymongo.cursor.Cursor object at 0x862c790>
      
          def _refresh(self):
              """Refreshes the cursor with more data from Mongo.
          
                  Returns the length of self.__data after refresh. Will exit early if
                  self.__data is already non-empty. Raises OperationFailure when the
                  cursor cannot be refreshed due to an error on the query.
                  """
              if len(self.__data) or self.__killed:
                  return len(self.__data)
          
              if self.__id is None:  # Query
                  ntoreturn = self.__batch_size
                  if self.__limit:
                      if self.__batch_size:
                          ntoreturn = min(self.__limit, self.__batch_size)
                      else:
                          ntoreturn = self.__limit
                  self.__send_message(
                      message.query(self.__query_options(),
                                    self.__collection.full_name,
                                    self.__skip, ntoreturn,
                                    self.__query_spec(), self.__fields,
                                    self.__uuid_subtype))
                  if not self.__id:
                      self.__killed = True
              elif self.__id:  # Get More
                  if self.__limit:
                      limit = self.__limit - self.__retrieved
                      if self.__batch_size:
                          limit = min(limit, self.__batch_size)
                  else:
                      limit = self.__batch_size
          
                  self.__send_message(
                      message.get_more(self.__collection.full_name,
      >                                limit, self.__id))
      
      /users/is/ahlpypi/egg_cache/p/pymongo-2.4.2-py2.6-linux-x86_64.egg/pymongo/cursor.py:776: 
      _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
      
      self = <pymongo.cursor.Cursor object at 0x862c790>
      message = (2007905771, ';\x00\x00\x00\xeb5\xaew\x00\x00\x00\x00\xd5\x07\x00\x00\x00\x00\x00\x00mongoose.system.namespaces\x00\x00\x00\x00\x00\x02\x10C&\x1b\xf0,3')
      
          def __send_message(self, message):
              """Send a query or getmore message and handles the response.
                  """
              db = self.__collection.database
              kwargs = {"_must_use_master": self.__must_use_master}
              kwargs["read_preference"] = self.__read_preference
              kwargs["tag_sets"] = self.__tag_sets
              kwargs["secondary_acceptable_latency_ms"] = (
                  self.__secondary_acceptable_latency_ms)
              if self.__connection_id is not None:
                  kwargs["_connection_to_use"] = self.__connection_id
              kwargs.update(self.__kwargs)
          
              try:
                  response = db.connection._send_message_with_response(message,
      >                                                                **kwargs)
      
      /users/is/ahlpypi/egg_cache/p/pymongo-2.4.2-py2.6-linux-x86_64.egg/pymongo/cursor.py:700: 
      _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
      
      self = MongoClient(['cn14:27119', 'localhost:27119'])
      message = (2007905771, ';\x00\x00\x00\xeb5\xaew\x00\x00\x00\x00\xd5\x07\x00\x00\x00\x00\x00\x00mongoose.system.namespaces\x00\x00\x00\x00\x00\x02\x10C&\x1b\xf0,3')
      _must_use_master = True
      kwargs = {'read_preference': 0, 'secondary_acceptable_latency_ms': 15.0, 'tag_sets': [{}]}
      sock_info = SocketInfo(<socket._socketobject object at 0xbae8520>) CLOSED at 140690896
      
          def _send_message_with_response(self, message,
                                          _must_use_master=False, **kwargs):
              """Send a message to Mongo and return the response.
          
                  Sends the given message and returns the response.
          
                  :Parameters:
                    - `message`: (request_id, data) pair making up the message to send
                  """
              sock_info = self.__socket()
          
              try:
                  try:
                      if "network_timeout" in kwargs:
                          sock_info.sock.settimeout(kwargs["network_timeout"])
      >               return self.__send_and_receive(message, sock_info)
      
      /users/is/ahlpypi/egg_cache/p/pymongo-2.4.2-py2.6-linux-x86_64.egg/pymongo/mongo_client.py:915: 
      _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
      
      self = MongoClient(['cn14:27119', 'localhost:27119'])
      message = (2007905771, ';\x00\x00\x00\xeb5\xaew\x00\x00\x00\x00\xd5\x07\x00\x00\x00\x00\x00\x00mongoose.system.namespaces\x00\x00\x00\x00\x00\x02\x10C&\x1b\xf0,3')
      sock_info = SocketInfo(<socket._socketobject object at 0xbae8520>) CLOSED at 140690896
      
          def __send_and_receive(self, message, sock_info):
              """Send a message on the given socket and return the response data.
                  """
              (request_id, data) = self.__check_bson_size(message)
              try:
                  sock_info.sock.sendall(data)
      >           return self.__receive_message_on_socket(1, request_id, sock_info)
      
      /users/is/ahlpypi/egg_cache/p/pymongo-2.4.2-py2.6-linux-x86_64.egg/pymongo/mongo_client.py:893: 
      _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
      
      self = MongoClient(['cn14:27119', 'localhost:27119']), operation = 1
      request_id = 2007905771
      sock_info = SocketInfo(<socket._socketobject object at 0xbae8520>) CLOSED at 140690896
      
          def __receive_message_on_socket(self, operation, request_id, sock_info):
              """Receive a message in response to `request_id` on `sock`.
          
                  Returns the response data with the header removed.
                  """
              header = self.__receive_data_on_socket(16, sock_info)
              length = struct.unpack("<i", header[:4])[0]
              assert request_id == struct.unpack("<i", header[8:12])[0], \
                  "ids don't match %r %r" % (request_id,
                                             struct.unpack("<i", header[8:12])[0])
              assert operation == struct.unpack("<i", header[12:])[0]
          
      >       return self.__receive_data_on_socket(length - 16, sock_info)
      
      /users/is/ahlpypi/egg_cache/p/pymongo-2.4.2-py2.6-linux-x86_64.egg/pymongo/mongo_client.py:885: 
      _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
      
      self = MongoClient(['cn14:27119', 'localhost:27119']), length = 26283
      sock_info = SocketInfo(<socket._socketobject object at 0xbae8520>) CLOSED at 140690896
      
          def __receive_data_on_socket(self, length, sock_info):
              """Lowest level receive operation.
          
                  Takes length to receive and repeatedly calls recv until able to
                  return a buffer of that length, raising ConnectionFailure on error.
                  """
              message = EMPTY
              while length:
      >           chunk = sock_info.sock.recv(length)
      E           Failed: Timeout >600s
      
      /users/is/ahlpypi/egg_cache/p/pymongo-2.4.2-py2.6-linux-x86_64.egg/pymongo/mongo_client.py:866: Failed
      
      

      It's unclear what the underling cause is...

            Assignee:
            jesse@mongodb.com A. Jesse Jiryu Davis
            Reporter:
            jblackburn James Blackburn
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: