def receive_loop(self, msgs_callback): """ Receive messages until shutdown @param msgs_callback: callback to invoke for new messages received @type msgs_callback: fn([msg]) """ # - use assert here as this would be an internal error, aka bug logger.debug("receive_loop for [%s]", self.name) try: try: while not self.done and not is_shutdown(): msgs = self.receive_once() if not self.done and not is_shutdown(): msgs_callback(msgs) rospydebug("receive_loop[%s]: done condition met, exited loop"%self.name) except DeserializationError as e: logerr("[%s] error deserializing incoming request: %s"%self.name, str(e)) rospyerr("[%s] error deserializing incoming request: %s"%self.name, traceback.format_exc()) except: # in many cases this will be a normal hangup, but log internally try: #1467 sometimes we get exceptions due to #interpreter shutdown, so blanket ignore those if #the reporting fails rospydebug("exception in receive loop for [%s], may be normal. Exception is %s",self.name, traceback.format_exc()) except: pass finally: if not self.done: self.close()
def receive_loop(self, msgs_callback): """ Receive messages until shutdown @param msgs_callback: callback to invoke for new messages received @type msgs_callback: fn([msg]) """ # - use assert here as this would be an internal error, aka bug logger.debug("receive_loop for [%s]", self.name) try: while not self.done and not is_shutdown(): try: if self.socket is not None: msgs = self.receive_once() if not self.done and not is_shutdown(): msgs_callback(msgs, self) else: self._reconnect() except TransportException as e: # set socket to None so we reconnect try: if self.socket is not None: try: self.socket.shutdown() except: pass finally: self.socket.close() except: pass self.socket = None except DeserializationError as e: #TODO: how should we handle reconnect in this case? logerr( "[%s] error deserializing incoming request: %s" % self.name, str(e)) rospyerr( "[%s] error deserializing incoming request: %s" % self.name, traceback.format_exc()) except: # in many cases this will be a normal hangup, but log internally try: #1467 sometimes we get exceptions due to #interpreter shutdown, so blanket ignore those if #the reporting fails rospydebug( "exception in receive loop for [%s], may be normal. Exception is %s", self.name, traceback.format_exc()) except: pass rospydebug("receive_loop[%s]: done condition met, exited loop" % self.name) finally: if not self.done: self.close()
def write_data(self, data): """ Write raw data to transport @raise TransportInitialiationError: could not be initialized @raise TransportTerminated: no longer open for publishing """ if not self.socket: raise TransportInitError( "TCPROS transport was not successfully initialized") if self.done: raise TransportTerminated("connection closed") try: #TODO: get rid of sendalls and replace with async-style publishing self.socket.sendall(data.encode()) self.stat_bytes += len(data) self.stat_num_msg += 1 except IOError as xxx_todo_changeme: #for now, just document common errno's in code (errno, msg) = xxx_todo_changeme.args #for now, just document common errno's in code if errno == 32: #broken pipe logdebug("ERROR: Broken Pipe") self.close() raise TransportTerminated(str(errno) + msg) raise #re-raise except socket.error as xxx_todo_changeme1: #for now, just document common errno's in code (errno, msg) = xxx_todo_changeme1.args #for now, just document common errno's in code if errno == 32: #broken pipe logdebug("[%s]: Closing connection [%s] due to broken pipe", self.name, self.endpoint_id) self.close() raise TransportTerminated(msg) elif errno == 104: #connection reset by peer logdebug("[%s]: Peer [%s] has closed connection", self.name, self.endpoint_id) self.close() raise TransportTerminated(msg) else: rospydebug("unknown socket error writing data: %s", traceback.format_exc()) logdebug( "[%s]: closing connection [%s] due to unknown socket error: %s", self.name, self.endpoint_id, msg) self.close() raise TransportTerminated(str(errno) + ' ' + msg) #except: #TODO: try to figure out common errors here #raise return True
def write_data(self, data): """ Write raw data to transport @raise TransportInitialiationError: could not be initialized @raise TransportTerminated: no longer open for publishing """ if not self.socket: raise TransportInitError("TCPROS transport was not successfully initialized") if self.done: raise TransportTerminated("connection closed") try: #TODO: get rid of sendalls and replace with async-style publishing self.socket.sendall(data.encode()) self.stat_bytes += len(data) self.stat_num_msg += 1 except IOError as xxx_todo_changeme: #for now, just document common errno's in code (errno, msg) = xxx_todo_changeme.args #for now, just document common errno's in code if errno == 32: #broken pipe logdebug("ERROR: Broken Pipe") self.close() raise TransportTerminated(str(errno)+msg) raise #re-raise except socket.error as xxx_todo_changeme1: #for now, just document common errno's in code (errno, msg) = xxx_todo_changeme1.args #for now, just document common errno's in code if errno == 32: #broken pipe logdebug("[%s]: Closing connection [%s] due to broken pipe", self.name, self.endpoint_id) self.close() raise TransportTerminated(msg) elif errno == 104: #connection reset by peer logdebug("[%s]: Peer [%s] has closed connection", self.name, self.endpoint_id) self.close() raise TransportTerminated(msg) else: rospydebug("unknown socket error writing data: %s",traceback.format_exc()) logdebug("[%s]: closing connection [%s] due to unknown socket error: %s", self.name, self.endpoint_id, msg) self.close() raise TransportTerminated(str(errno)+' '+msg) #except: #TODO: try to figure out common errors here #raise return True
def callback_loop(self, msgs_callback): while not self.done and not is_shutdown(): try: with self.msg_queue_lock: # Data that was leftover from reading header may have made # messages immediately available (such as from a latched # topic). Go ahead and process anything we already have before # waiting. while self.msg_queue: msg = self.msg_queue.pop(0) # Be sure to not hold the message queue lock while calling # the callback, it may take a while. self.msg_queue_lock.release() msgs_callback([msg], self) self.msg_queue_lock.acquire() self.msg_queue_condition.wait() except: # in many cases this will be a normal hangup, but log internally try: #1467 sometimes we get exceptions due to #interpreter shutdown, so blanket ignore those if #the reporting fails rospydebug("exception in callback loop for [%s], may be normal. Exception is %s",self.name, traceback.format_exc()) except: pass
def receive_loop(self, msgs_callback): """ Receive messages until shutdown @param msgs_callback: callback to invoke for new messages received @type msgs_callback: fn([msg]) """ # - use assert here as this would be an internal error, aka bug logger.debug("receive_loop for [%s]", self.name) try: try: while not self.done and not is_shutdown(): msgs = self.receive_once() if not self.done and not is_shutdown(): msgs_callback(msgs) rospydebug( "receive_loop[%s]: done condition met, exited loop" % self.name) except DeserializationError, e: logerr( "[%s] error deserializing incoming request: %s" % self.name, str(e)) rospyerr( "[%s] error deserializing incoming request: %s" % self.name, traceback.format_exc()) except: # in many cases this will be a normal hangup, but log internally try: #1467 sometimes we get exceptions due to #interpreter shutdown, so blanket ignore those if #the reporting fails rospydebug( "exception in receive loop for [%s], may be normal. Exception is %s", self.name, traceback.format_exc()) except: pass
def receive_loop(self, msgs_callback): """ Receive messages until shutdown @param msgs_callback: callback to invoke for new messages received @type msgs_callback: fn([msg]) """ # - use assert here as this would be an internal error, aka bug logger.debug("receive_loop for [%s]", self.name) # Start a callback thread to process the callbacks. This way the # receive loop can continue calling recv() while a long-running # callback is running. try: self.msg_queue = [] self.msg_queue_lock = threading.Lock() self.msg_queue_condition = threading.Condition(self.msg_queue_lock) callback_thread = threading.Thread( target=self.callback_loop, args=(msgs_callback,)) callback_thread.start() while not self.done and not is_shutdown(): try: if self.socket is not None: msgs = self.receive_once() if not self.done and not is_shutdown(): with self.msg_queue_lock: self.msg_queue += msgs if self.protocol.queue_size is not None: self.msg_queue = self.msg_queue[-self.protocol.queue_size:] self.msg_queue_condition.notify() else: self._reconnect() except TransportException as e: # set socket to None so we reconnect try: if self.socket is not None: try: self.socket.shutdown() except: pass finally: self.socket.close() except: pass self.socket = None except DeserializationError as e: #TODO: how should we handle reconnect in this case? logerr("[%s] error deserializing incoming request: %s"%(self.name, str(e))) rospyerr("[%s] error deserializing incoming request: %s"%(self.name, traceback.format_exc())) except: # in many cases this will be a normal hangup, but log internally try: #1467 sometimes we get exceptions due to #interpreter shutdown, so blanket ignore those if #the reporting fails rospydebug("exception in receive loop for [%s], may be normal. Exception is %s",self.name, traceback.format_exc()) except: pass with self.msg_queue_lock: self.msg_queue_condition.notify() callback_thread.join() rospydebug("receive_loop[%s]: done condition met, exited loop"%self.name) finally: if not self.done: self.close()
raise TransportTerminated(str(errno) + msg) raise #re-raise except socket.error, (errno, msg): #for now, just document common errno's in code if errno == 32: #broken pipe logdebug("[%s]: Closing connection [%s] due to broken pipe", self.name, self.endpoint_id) self.close() raise TransportTerminated(msg) elif errno == 104: #connection reset by peer logdebug("[%s]: Peer [%s] has closed connection", self.name, self.endpoint_id) self.close() raise TransportTerminated(msg) else: rospydebug("unknown socket error writing data: %s", traceback.format_exc()) logdebug( "[%s]: closing connection [%s] due to unknown socket error: %s", self.name, self.endpoint_id, msg) self.close() raise TransportTerminated(str(errno) + ' ' + msg) except: #TODO: try to figure out common errors here raise return True def receive_once(self): """ block until messages are read off of socket @return: list of newly received messages @rtype: [Msg]