No error on lost connection w/pyserial

Posted on
Thu Dec 19, 2013 1:38 am
berkinet offline
User avatar
Posts: 3290
Joined: Nov 18, 2008
Location: Berkeley, CA, USA & Mougins, France

No error on lost connection w/pyserial

There appears to have been a bug in pyserial that allowed a socket connection to drop without raising an error (I.e. it just keeps on listening to nothing). The issue was fixed in pyserial 2.7 in October. This bug creates an issue for code that connects to a remote socket and listen for data using readline. Because the data might arrive at infrequent intervals, timeouts are not practical.

Bottom line, if possible, can you update the pyserial included in Indigo to pyserial 2.7, or see if the pyserial 2.7 fix can be back ported to the version included in Indigo.

Or, is there a work-around?

EDIT: I tried switching to openSerial() but still have the same issue.

with serial_for_url:
    self.plugin.conn = serial.serial_for_url(theURL, baudrate=115200)
and with openSerial
    self.plugin.conn = self.plugin.openSerial('foo', theURL, 115200, timeout=1, writeTimeout=1, errorLogFunc=self.errorLog)

Posted on
Thu Dec 19, 2013 7:44 am
matt (support) offline
Site Admin
User avatar
Posts: 21417
Joined: Jan 27, 2003
Location: Texas

Re: No error on lost connection w/pyserial

This is under Indigo 6.0.7? We actually updated to pyserial 2.7 for Indigo 6.0.6, so that fix should be in there. That pyserial update was the cause of some problems as you know which forced us to release 6.0.7.

Image

Posted on
Thu Dec 19, 2013 10:41 am
berkinet offline
User avatar
Posts: 3290
Joined: Nov 18, 2008
Location: Berkeley, CA, USA & Mougins, France

Re: No error on lost connection w/pyserial

matt (support) wrote:
This is under Indigo 6.0.7? We actually updated to pyserial 2.7 for Indigo 6.0.6, so that fix should be in there. That pyserial update was the cause of some problems as you know which forced us to release 6.0.7.

I thought that might be the case. Yet, I still don't get any errors raised when the connection is lost. Any ideas?

Also, I know my call to serial_for_url uses the embedded pyserial, because, as you note! it broke in 6.0.6. What does openSerial call?

Posted on
Thu Dec 19, 2013 10:53 am
matt (support) offline
Site Admin
User avatar
Posts: 21417
Joined: Jan 27, 2003
Location: Texas

Re: No error on lost connection w/pyserial

openSerial is just a wrapper around serial_for_url:

Code: Select all
   def openSerial(self, ownerName, portUrl, baudrate, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, timeout=None, xonxoff=False, rtscts=False, writeTimeout=None, dsrdtr=False, interCharTimeout=None, errorLogFunc=None):
      if errorLogFunc is None:
         errorLogFunc = self.errorLog

      if not isinstance(portUrl, (str, unicode)) or len(portUrl) == 0:
         errorLogFunc(u"valid serial port not selected for \"%s\"" % (ownerName,))
         return None

      try:
         return serial.serial_for_url(portUrl, baudrate=baudrate, bytesize=bytesize, parity=parity, stopbits=stopbits, timeout=timeout, xonxoff=xonxoff, rtscts=rtscts, writeTimeout=writeTimeout, dsrdtr=dsrdtr, interCharTimeout=interCharTimeout)
      except Exception, exc:
         portUrl_lower = portUrl.lower()
         errorLogFunc(u"\"%s\" serial port open error: %s" % (ownerName, str(exc)))
         if "no 35" in str(exc):
            errorLogFunc(u"the specified serial port is used by another interface or device")
         elif portUrl_lower.startswith('rfc2217://') or portUrl_lower.startswith('socket://'):
            errorLogFunc(u"make sure remote serial server IP address and port number are correct")
         else:
            errorLogFunc(u"make sure the USB virtual serial port driver (ex: FTDI driver) is installed and correct port is selected")
         return None


It will catch the error and not re-raise it, but it should show the error in the Event Log (and it returns None if there is an error). I wonder if the bug either wasn't fixed, or if this is a slightly different bug.

Image

Posted on
Thu Dec 19, 2013 12:59 pm
berkinet offline
User avatar
Posts: 3290
Joined: Nov 18, 2008
Location: Berkeley, CA, USA & Mougins, France

Re: No error on lost connection w/pyserial

Well, I found a work-around...

If I set the connection timeout to None

Then I can look for a null read from readline
    rawData = conn.readline()
    if rawData == '':
      errorLog("Connection Lost")
      exit()

I'm still not sure why pyserial isn't raising the exception. But, I did find this comment from one mmb in urlhandler/protocol_socket.py in an earlier version of the pyserial included in Indigo :wink:
    # One could argue that this should throw the exception up to
    # the caller (which might be serialutil's readline). However,
    # based on the description comment for this function, it sounds
    # like the author wants it to just return out if there was a
    # timeout without the complete data. This doesn't seem quite
    # right to me, but fixing this to throw would be a change in
    # the semantics of the function AND rfc2217.py would need a
    # similar change (both should behave the same way). If this
    # the current behavior ends up causing problems, then we should
    # revisit this to have it throw an exception. 2012.02.10 (mmb)

Posted on
Thu Dec 19, 2013 1:14 pm
matt (support) offline
Site Admin
User avatar
Posts: 21417
Joined: Jan 27, 2003
Location: Texas

Re: No error on lost connection w/pyserial

Hah. I had forgotten about that. I think my changes there ended up dropping out with the 2.7 upgrade. My change didn't throw an exception on no data, but handled some other problems that ended up being resolved by 2.7.

I do agree it doesn't seem right for an exception not to be thrown when the socket dies. Sounds like it is still buggy, IMO.

Image

Posted on
Fri Dec 20, 2013 1:56 pm
berkinet offline
User avatar
Posts: 3290
Joined: Nov 18, 2008
Location: Berkeley, CA, USA & Mougins, France

Re: No error on lost connection w/pyserial

berkinet wrote:
Well, I found a work-around...


Or not. Looking for a null line with readline works if the socket it is listening to shuts down in an orderly manner. However, it does not catch a failure outside the socket serving program. Like, a disconnect of the network connection, or a power failure. Since nothing, even a null, is received, there is nothing to trigger a failure response on.

I will probably reset a countdown timer after each read, and then attempt a write when the timer expires, then reset the timer...

How have others dealt with this problem? Does twisted do a better job?

Page 1 of 1

Who is online

Users browsing this forum: No registered users and 7 guests