Keeps track of previously found pids and avoids re-reading those comm files if not of interest
| 5 | |
| 6 | |
| 7 | class ProcessReader: |
| 8 | ''' |
| 9 | Keeps track of previously found pids and avoids re-reading those |
| 10 | comm files if not of interest |
| 11 | ''' |
| 12 | |
| 13 | def __init__(self, profiles=None): |
| 14 | self.triggerapps = self._get_triggerapps(profiles) |
| 15 | self.triggerapps_found = set() |
| 16 | self.profiles = profiles |
| 17 | self.pid_names = dict() |
| 18 | self.pids_last = set() |
| 19 | self.update() |
| 20 | |
| 21 | def update(self): |
| 22 | # ensure previously identified pids are checked |
| 23 | pids_new = set() |
| 24 | comms = glob('/proc/[0-9]*/comm') |
| 25 | for comm in comms + [f'/proc/{pid}/comm' for pid in self.pid_names]: |
| 26 | pid = int(comm.split('/')[2]) |
| 27 | |
| 28 | # If pid was seen last time but wasn't of interest |
| 29 | if pid in self.pids_last and pid not in self.pid_names: |
| 30 | pids_new.add(pid) |
| 31 | continue |
| 32 | |
| 33 | try: |
| 34 | with open(comm, 'r') as file: |
| 35 | proc_name = file.readline().strip() |
| 36 | if proc_name in self.triggerapps: |
| 37 | self.pid_names[pid] = proc_name |
| 38 | except (FileNotFoundError, ProcessLookupError): |
| 39 | # FileNotFoundError : process exited before being read |
| 40 | # ProcessLookupError: process exited while being open, before readline() |
| 41 | if pid in self.pid_names: |
| 42 | _ = self.pid_names.pop(pid) |
| 43 | else: |
| 44 | pids_new.add(pid) |
| 45 | |
| 46 | self.pids_last = pids_new |
| 47 | self.triggerapps_found = set(self.pid_names.values()) |
| 48 | |
| 49 | def reset(self, profiles): |
| 50 | ''' |
| 51 | Updates self.triggerapps and clears self.pids_last |
| 52 | useful for hot-reloading profiles |
| 53 | ''' |
| 54 | self.__init__(profiles=profiles) |
| 55 | |
| 56 | def _get_triggerapps(self, profiles=None) -> set: |
| 57 | if profiles is None: |
| 58 | profiles = config.read_profiles() |
| 59 | triggerapps = set() |
| 60 | for profile_name in profiles: |
| 61 | triggerapps.update([p[:15] for p in profiles[profile_name].triggerapps]) |
| 62 | return triggerapps |
| 63 | |
| 64 | def triggered_profile(self) -> config.PowerProfile: |