def monitor_process(self, origin_pid: Pid, target, ref=None): """ Locate the process referenced by the target and place the origin pid into its ``monitors_`` collection. When something happens to the ``target``, a special message will be sent to the ``origin``. Remote targets are supported. :param ref: If not None, will be reused, else a new random ref will be generated. :type ref: None or term.reference.Reference :type origin_pid: term.pid.Pid :param origin_pid: The (possibly remote) process who will be monitoring the target from now and wants to know when we exit. :type target: term.pid.Pid or term.atom.Atom :param target: Name or pid of a monitor target process. :rtype: term.reference.Reference :raises pyrlang.node.ProcessNotFoundError: if target does not exist. """ target_pid = self.where_is(target) m_ref = ref if ref is not None \ else Reference.create(node_name=self.node_name_, creation=self.dist_.creation_) if not origin_pid.is_local_to(self): # Origin is remote and wants to monitor local process return self._monitor_local_process(origin_pid, target_pid, m_ref) if target_pid.is_local_to(self): # Target is local and we notify a local process return self._monitor_local_process(origin_pid, target_pid, m_ref) # Target is remote and a distribution message has to be sent return self._monitor_remote_process(origin_pid, target_pid, m_ref)
def _monitor_remote_process(self, origin_pid: Pid, target_pid: Pid, ref: Reference): monitor_msg = ('monitor_p', origin_pid, target_pid, ref) self._dist_command(receiver_node=target_pid.node_name_, message=monitor_msg) # if the origin is local, register monitor in it. Remote pids are # handled by the remote assert origin_pid.is_local_to(self) origin_p = self.where_is_process(origin_pid) origin_p.add_monitor(pid=target_pid, ref=ref)
def _demonitor_local_process(self, origin_pid: Pid, target_pid: Pid, ref: Reference): target_proc = self.processes_.get(target_pid, None) if target_proc is not None: target_proc.remove_monitored_by(ref=ref, pid=origin_pid) else: msg = "Demonitor target %s does not exist" % target_pid LOG.error(msg) raise ProcessNotFoundError(msg) # if the origin is local, unregister monitor from it # Remotely set monitors have remote origin if origin_pid.is_local_to(self): origin_p = self.where_is_process(origin_pid) origin_p.remove_monitor(ref=ref, pid=target_pid)
def _monitor_local_process(self, origin_pid: Pid, target_pid: Pid, ref: Reference): """ Monitor a local target. """ target_proc = self.processes_.get(target_pid, None) # LOG.info("Monitor: orig=%s targ=%s -> %s", origin, target, target_proc) if target_proc is not None: target_proc.add_monitored_by(pid=origin_pid, ref=ref) else: msg = "Monitor target %s does not exist" % target_pid LOG.error(msg) raise ProcessNotFoundError(msg) # if the origin is local, register monitor in it. # Remotely set monitors have remote origin if origin_pid.is_local_to(self): origin_p = self.where_is_process(origin_pid) origin_p.add_monitor(pid=target_proc.pid_, ref=ref)