def get_children(self, recursive=False): """Return the children of this process as a list of Process objects. If recursive is True return all the parent descendants. Example (A == this process): A ─┐ │ ├─ B (child) ─┐ │ └─ X (grandchild) ─┐ │ └─ Y (great grandchild) ├─ C (child) └─ D (child) >>> p.get_children() B, C, D >>> p.get_children(recursive=True) B, X, Y, C, D Note that in the example above if process X disappears process Y won't be returned either as the reference to process A is lost. """ if not self.is_running(): name = self._platform_impl._process_name raise NoSuchProcess(self.pid, name) ret = [] if not recursive: for p in process_iter(): try: if p.ppid == self.pid: ret.append(p) except NoSuchProcess: pass else: # construct a dict where 'values' are all the processes # having 'key' as their parent table = defaultdict(list) for p in process_iter(): try: table[p.ppid].append(p) except NoSuchProcess: pass # At this point we have a mapping table where table[self.pid] # are the current process's children. # Below, we look for all descendants recursively, similarly # to a recursive function call. checkpids = [self.pid] for pid in checkpids: for proc in table[pid]: ret.append(proc) if proc.pid not in checkpids: checkpids.append(proc.pid) return ret
def get_proc_inodes(self, pid): inodes = defaultdict(list) for fd in os.listdir("/proc/%s/fd" % pid): try: inode = os.readlink("/proc/%s/fd/%s" % (pid, fd)) except OSError: # TODO: need comment here continue else: if inode.startswith('socket:['): # the process is using a socket inode = inode[8:][:-1] inodes[inode].append((pid, int(fd))) return inodes
def get_children(self, recursive=False): """Return the children of this process as a list of Process objects pre-emptively checking whether PID has been reused. If recursive is True return all the parent descendants. Example (A == this process): A ─┐ │ ├─ B (child) ─┐ │ └─ X (grandchild) ─┐ │ └─ Y (great grandchild) ├─ C (child) └─ D (child) >>> p.get_children() B, C, D >>> p.get_children(recursive=True) B, X, Y, C, D Note that in the example above if process X disappears process Y won't be returned either as the reference to process A is lost. """ ret = [] if not recursive: for p in process_iter(): try: if p.ppid == self.pid: # if child happens to be older than its parent # (self) it means child's PID has been reused if self.create_time <= p.create_time: ret.append(p) except NoSuchProcess: pass else: # construct a dict where 'values' are all the processes # having 'key' as their parent table = defaultdict(list) for p in process_iter(): try: table[p.ppid].append(p) except NoSuchProcess: pass # At this point we have a mapping table where table[self.pid] # are the current process's children. # Below, we look for all descendants recursively, similarly # to a recursive function call. checkpids = [self.pid] for pid in checkpids: for child in table[pid]: try: # if child happens to be older than its parent # (self) it means child's PID has been reused intime = self.create_time <= child.create_time except NoSuchProcess: pass else: if intime: ret.append(child) if child.pid not in checkpids: checkpids.append(child.pid) return ret