def _receiver(self): last_none = 0 while self._running: dtx = self._is.recv_dtx(self._cli, 2) # s if dtx is None: # 长时间没有回调则抛出错误 cur = time.time() if cur - last_none < 0.1: break last_none = cur continue self._next_identifier = max(self._next_identifier, dtx.identifier + 1) wait_key = (dtx.channel_code, dtx.identifier) if wait_key in self._sync_waits: param = self._sync_waits[wait_key] param['result'] = dtx param['event'].set() elif 2 ** 32 - dtx.channel_code in self._channel_callbacks: try: self._channel_callbacks[2 ** 32 - dtx.channel_code](InstrumentRPCResult(dtx)) except: traceback.print_exc() else: try: selector = selector_to_pyobject(dtx.get_selector()) except: selector = None if selector and type(selector) is str and selector in self._callbacks: try: ret = self._callbacks[selector](InstrumentRPCResult(dtx)) if dtx.expects_reply: reply = dtx.new_reply() reply.set_selector(pyobject_to_selector(ret)) reply._payload_header.flags = 0x3 self._is.send_dtx(self._cli, reply) except: traceback.print_exc() else: if self._unhanled_callback: try: self._unhanled_callback(InstrumentRPCResult(dtx)) except: traceback.print_exc() self._receiver_exiting = True # to block incoming calls for wait_key in self._sync_waits: self._sync_waits[wait_key]['result'] = InstrumentServiceConnectionLost self._sync_waits[wait_key]['event'].set()
def _call(self, sync: bool, channel_id: int, selector: str, *auxiliaries): if self._receiver_exiting: raise RuntimeWarning("rpc service died") dtx = DTXMessage() dtx.identifier = self._next_identifier self._next_identifier += 1 dtx.channel_code = channel_id dtx.set_selector(pyobject_to_selector(selector)) wait_key = (dtx.channel_code, dtx.identifier) for aux in auxiliaries: if type(aux) is InstrumentRPCRawArg: dtx.add_auxiliary(aux.data) else: dtx.add_auxiliary(pyobject_to_auxiliary(aux)) if sync: dtx.expects_reply = True param = {"result": None, "event": Event()} self._sync_waits[wait_key] = param self._is.send_dtx(self._cli, dtx) # TODO: protect this line with mutex if sync: param['event'].wait() ret = param['result'] self._sync_waits.pop(wait_key) return ret
return ret ret += rb return ret def pre_start(self, rpc): pass def post_start(self, rpc): pass class InstrumentRPCParseError: pass InstrumentServiceConnectionLost = DTXMessage().set_selector(pyobject_to_selector("[PerfCat] Connection Lost!")) class InstrumentRPCRawArg: def __init__(self, data: bytes): self.data = data class InstrumentRPCResult: def __init__(self, dtx): self.raw = dtx if self.raw is None: self.xml = None self.parsed = None self.plist = None return