labath created this revision. labath added reviewers: tfiala, tberghammer. labath added a subscriber: lldb-commits. Herald added subscribers: srhines, danalbert, tberghammer.
Normally, when the remote stub is not ready, we will get ECONNREFUSED during the connect() attempt. However, due to the way how ADB forwarding works, on android targets the connect() will always be successful, but the connection will be immediately dropped if ADB could not connect on the remote side. This commit tries to detect this situation, and report it as "connection refused" so that the upper test layers attempt the connection again. http://reviews.llvm.org/D18146 Files: packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py Index: packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py =================================================================== --- packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py +++ packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py @@ -24,6 +24,9 @@ from lldbgdbserverutils import * import logging +class _ConnectionRefused(IOError): + pass + class GdbRemoteTestCaseBase(TestBase): _TIMEOUT_SECONDS = 7 @@ -265,6 +268,22 @@ subprocess.call(adb + [ "tcp:%d" % source, "tcp:%d" % target]) self.addTearDownHook(remove_port_forward) + def _verify_socket(self, sock): + # Normally, when the remote stub is not ready, we will get ECONNREFUSED during the + # connect() attempt. However, due to the way how ADB forwarding works, on android targets + # the connect() will always be successful, but the connection will be immediately dropped + # if ADB could not connect on the remote side. This function tries to detect this + # situation, and report it as "connection refused" so that the upper layers attempt the + # connection again. + triple = self.dbg.GetSelectedPlatform().GetTriple() + if not re.match(".*-.*-.*-android", triple): + return # Not android. + can_read, _, _ = select.select([sock], [], [], 0.1) + if sock not in can_read: + return # Data is available, connection is alive. + if len(sock.recv(1, socket.MSG_PEEK)) == 0: + raise _ConnectionRefused() # Got EOF, connection dropped. + def create_socket(self): sock = socket.socket() logger = self.logger @@ -275,7 +294,12 @@ logger.info("Connecting to debug monitor on %s:%d", self.stub_hostname, self.port) connect_info = (self.stub_hostname, self.port) - sock.connect(connect_info) + try: + sock.connect(connect_info) + except socket.error as serr: + if serr.errno == errno.ECONNREFUSED: + raise _ConnectionRefused() + raise serr def shutdown_socket(): if sock: @@ -292,6 +316,8 @@ self.addTearDownHook(shutdown_socket) + self._verify_socket(sock) + return sock def set_inferior_startup_launch(self): @@ -379,12 +405,12 @@ while connect_attemps < MAX_CONNECT_ATTEMPTS: # Create a socket to talk to the server try: + logger.info("Connect attempt %d", connect_attemps+1) self.sock = self.create_socket() return server - except socket.error as serr: - # We're only trying to handle connection refused. - if serr.errno != errno.ECONNREFUSED: - raise serr + except _ConnectionRefused as serr: + # Ignore, and try again. + pass time.sleep(0.5) connect_attemps += 1
Index: packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py =================================================================== --- packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py +++ packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py @@ -24,6 +24,9 @@ from lldbgdbserverutils import * import logging +class _ConnectionRefused(IOError): + pass + class GdbRemoteTestCaseBase(TestBase): _TIMEOUT_SECONDS = 7 @@ -265,6 +268,22 @@ subprocess.call(adb + [ "tcp:%d" % source, "tcp:%d" % target]) self.addTearDownHook(remove_port_forward) + def _verify_socket(self, sock): + # Normally, when the remote stub is not ready, we will get ECONNREFUSED during the + # connect() attempt. However, due to the way how ADB forwarding works, on android targets + # the connect() will always be successful, but the connection will be immediately dropped + # if ADB could not connect on the remote side. This function tries to detect this + # situation, and report it as "connection refused" so that the upper layers attempt the + # connection again. + triple = self.dbg.GetSelectedPlatform().GetTriple() + if not re.match(".*-.*-.*-android", triple): + return # Not android. + can_read, _, _ = select.select([sock], [], [], 0.1) + if sock not in can_read: + return # Data is available, connection is alive. + if len(sock.recv(1, socket.MSG_PEEK)) == 0: + raise _ConnectionRefused() # Got EOF, connection dropped. + def create_socket(self): sock = socket.socket() logger = self.logger @@ -275,7 +294,12 @@ logger.info("Connecting to debug monitor on %s:%d", self.stub_hostname, self.port) connect_info = (self.stub_hostname, self.port) - sock.connect(connect_info) + try: + sock.connect(connect_info) + except socket.error as serr: + if serr.errno == errno.ECONNREFUSED: + raise _ConnectionRefused() + raise serr def shutdown_socket(): if sock: @@ -292,6 +316,8 @@ self.addTearDownHook(shutdown_socket) + self._verify_socket(sock) + return sock def set_inferior_startup_launch(self): @@ -379,12 +405,12 @@ while connect_attemps < MAX_CONNECT_ATTEMPTS: # Create a socket to talk to the server try: + logger.info("Connect attempt %d", connect_attemps+1) self.sock = self.create_socket() return server - except socket.error as serr: - # We're only trying to handle connection refused. - if serr.errno != errno.ECONNREFUSED: - raise serr + except _ConnectionRefused as serr: + # Ignore, and try again. + pass time.sleep(0.5) connect_attemps += 1
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits