| 74 | |
| 75 | @contextmanager |
| 76 | def log_stats(self, process): |
| 77 | try: |
| 78 | process_handle = psutil.Process(self.get_pid(process.pid)) |
| 79 | except (psutil.AccessDenied, psutil.NoSuchProcess): |
| 80 | # Fetching process stats has an expected race condition with the |
| 81 | # running process, which might just have ended already. |
| 82 | yield ProcessStats() |
| 83 | return |
| 84 | |
| 85 | stats = ProcessStats() |
| 86 | finished = Event() |
| 87 | def run_logger(): |
| 88 | try: |
| 89 | while True: |
| 90 | stats.update(process_handle.memory_info()) |
| 91 | if finished.wait(self.probing_interval_sec): |
| 92 | break |
| 93 | except (psutil.AccessDenied, psutil.NoSuchProcess): |
| 94 | pass |
| 95 | |
| 96 | logger = Thread(target=run_logger) |
| 97 | logger.start() |
| 98 | try: |
| 99 | yield stats |
| 100 | finally: |
| 101 | finished.set() |
| 102 | |
| 103 | # Until we have joined the logger thread, we can't access the stats |
| 104 | # without a race condition. |
| 105 | logger.join() |
| 106 | |
| 107 | @contextmanager |
| 108 | def log_system_memory(self, log_path): |