def Run(self): """The main run method of the client. This method does not normally return. Only if there have been more than connection_error_limit failures, the method returns and allows the client to exit. """ while True: if self.http_manager.ErrorLimitReached(): return # Check if there is a message from the nanny to be sent. self.client_worker.SendNannyMessage() now = time.time() # Check with the foreman if we need to if (now > self.last_foreman_check + config.CONFIG["Client.foreman_check_frequency"]): # We must not queue messages from the comms thread with blocking=True # or we might deadlock. If the output queue is full, we can't accept # more work from the foreman anyways so it's ok to drop the message. try: self.client_worker.SendReply( rdf_protodict.DataBlob(), session_id=rdfvalue.FlowSessionID(flow_name="Foreman"), require_fastpoll=False, blocking=False) self.last_foreman_check = now except queue.Full: pass try: self.RunOnce() except Exception: # pylint: disable=broad-except # Catch everything, yes, this is terrible but necessary logging.warning("Uncaught exception caught: %s", traceback.format_exc()) if flags.FLAGS.pdb_post_mortem: pdb.post_mortem() # We suicide if our memory is exceeded, and there is no more work to do # right now. Our death should not result in loss of messages since we are # not holding any requests in our input queues. if (self.client_worker.MemoryExceeded() and not self.client_worker.IsActive() and self.client_worker.InQueueSize() == 0 and self.client_worker.OutQueueSize() == 0): logging.warning("Memory exceeded - exiting.") self.client_worker.SendClientAlert("Memory limit exceeded, exiting.") # Make sure this will return True so we don't get more work. # pylint: disable=g-bad-name self.client_worker.MemoryExceeded = lambda: True # pylint: enable=g-bad-name # Now send back the client message. self.RunOnce() # And done for now. sys.exit(-1) self.timer.Wait() self.client_worker.Heartbeat()
def _ForemanOp(self): """Sends Foreman checks periodically.""" period = config.CONFIG["Client.foreman_check_frequency"] self._threads["Worker"].SendReply( rdf_protodict.DataBlob(), session_id=rdfvalue.FlowSessionID(flow_name="Foreman"), require_fastpoll=False) time.sleep(period)
def SendNannyMessage(self): # We might be monitored by Fleetspeak. if not self.nanny_controller: return msg = self.nanny_controller.GetNannyMessage() if msg: self.SendReply( rdf_protodict.DataBlob(string=msg), session_id=rdfvalue.FlowSessionID(flow_name="NannyMessage"), require_fastpoll=False) self.nanny_controller.ClearNannyMessage()
def SendClientAlert(self, msg): self.SendReply( rdf_protodict.DataBlob(string=msg), session_id=rdfvalue.FlowSessionID(flow_name="ClientAlert"), require_fastpoll=False)
def SendForemanRequest(self): self.client_worker.SendReply( rdf_protodict.DataBlob(), session_id=rdfvalue.FlowSessionID(flow_name="Foreman"), require_fastpoll=False)