rfc2217: shutdown threads in case of errors in open()
diff --git a/serial/rfc2217.py b/serial/rfc2217.py
index a70df5f..4550ccf 100644
--- a/serial/rfc2217.py
+++ b/serial/rfc2217.py
@@ -441,36 +441,40 @@
# RFC 2217 flow control between server and client
self._remote_suspend_flow = False
+ self.is_open = True
self._thread = threading.Thread(target=self._telnetReadLoop)
self._thread.setDaemon(True)
self._thread.setName('pySerial RFC 2217 reader thread for %s' % (self._port,))
self._thread.start()
- # negotiate Telnet/RFC 2217 -> send initial requests
- for option in self._telnet_options:
- if option.state is REQUESTED:
- self.telnetSendOption(option.send_yes, option.option)
- # now wait until important options are negotiated
- timeout_time = time.time() + self._network_timeout
- while time.time() < timeout_time:
- time.sleep(0.05) # prevent 100% CPU load
- if sum(o.active for o in mandadory_options) == sum(o.state != INACTIVE for o in mandadory_options):
- break
- else:
- raise SerialException("Remote does not seem to support RFC2217 or BINARY mode %r" % mandadory_options)
- if self.logger:
- self.logger.info("Negotiated options: %s" % self._telnet_options)
+ try: # must clean-up if open fails
+ # negotiate Telnet/RFC 2217 -> send initial requests
+ for option in self._telnet_options:
+ if option.state is REQUESTED:
+ self.telnetSendOption(option.send_yes, option.option)
+ # now wait until important options are negotiated
+ timeout_time = time.time() + self._network_timeout
+ while time.time() < timeout_time:
+ time.sleep(0.05) # prevent 100% CPU load
+ if sum(o.active for o in mandadory_options) == sum(o.state != INACTIVE for o in mandadory_options):
+ break
+ else:
+ raise SerialException("Remote does not seem to support RFC2217 or BINARY mode %r" % mandadory_options)
+ if self.logger:
+ self.logger.info("Negotiated options: %s" % self._telnet_options)
- # fine, go on, set RFC 2271 specific things
- self._reconfigure_port()
- # all things set up get, now a clean start
- self.is_open = True
- if not self._dsrdtr:
- self._update_dtr_state()
- if not self._rtscts:
- self._update_rts_state()
- self.reset_input_buffer()
- self.reset_output_buffer()
+ # fine, go on, set RFC 2271 specific things
+ self._reconfigure_port()
+ # all things set up get, now a clean start
+ if not self._dsrdtr:
+ self._update_dtr_state()
+ if not self._rtscts:
+ self._update_rts_state()
+ self.reset_input_buffer()
+ self.reset_output_buffer()
+ except:
+ self.close()
+ raise
def _reconfigure_port(self):
"""Set communication parameters on opened port."""
@@ -518,20 +522,20 @@
def close(self):
"""Close port"""
- if self.is_open:
- if self._socket:
- try:
- self._socket.shutdown(socket.SHUT_RDWR)
- self._socket.close()
- except:
- # ignore errors.
- pass
- self._socket = None
- if self._thread:
- self._thread.join()
- self.is_open = False
+ self.is_open = False
+ if self._socket:
+ try:
+ self._socket.shutdown(socket.SHUT_RDWR)
+ self._socket.close()
+ except:
+ # ignore errors.
+ pass
+ if self._thread:
+ self._thread.join(7) # XXX more than socket timeout
+ self._thread = None
# in case of quick reconnects, give the server some time
time.sleep(0.3)
+ self._socket = None
def from_url(self, url):
"""extract host and port from an URL string"""
@@ -696,7 +700,7 @@
mode = M_NORMAL
suboption = None
try:
- while self._socket is not None:
+ while self.is_open:
try:
data = self._socket.recv(1024)
except socket.timeout: