Commit 7315161
Fix perf hook teardown hang via process-group signaling and bounded waits
Summary:
The `perf` hook (used as `-k perf` or as part of `-k fb_chef_off_turbo_on fb_stop_dynologd perf`) was hanging indefinitely on benchmark completion. Symptom: after the benchmark JSON metrics had been written, the parent `./benchpress run` Python stayed alive forever waiting on `subprocess.Popen.wait()` for the perf collector bash scripts. On BGM the hung children were `collect_amd_perf_counters.sh` + `collect_amd_zen4_perf_counters.sh`; on Grace the analog was `collect_nvda_neoversev2_perf_counters.sh`. This blocked every overnight automation run that used the perf hook, and required manually `kill -9`-ing the collector PIDs.
Root cause:
`Monitor.terminate()` did `os.kill(self.proc.pid, signal.SIGINT)` followed by an *unbounded* `self.proc.wait()`. But `self.proc` is the bash interpreter PID running the collector script; bash does NOT synchronously forward signals to its `wait`-blocked foreground child (`perf stat`). Even when the collector script's SIGINT trap eventually fires, the parent Python is also blocked on the output-catcher thread's `readline()` until the pipe closes, which only happens after bash exits. On AMD hosts the two simultaneous collectors (`perfutil` + `perfutil_zen4`) compete for the PMU and one of them can hang at startup — its `wait()` therefore never returns. No timeout anywhere → indefinite hang.
Fix (centralized in `Monitor.terminate()`):
1. **Process-group signaling.** `os.killpg(os.getpgid(self.proc.pid), SIGINT)` so both the bash wrapper and its `perf stat` child receive SIGINT in the same atomic delivery. Requires the Popen to have been started with `start_new_session=True` so a new pgid was created.
2. **Bounded waits.** `self.proc.wait(timeout=15)` after SIGINT; if it times out, escalate to `os.killpg(..., SIGKILL)` with another `wait(timeout=5)`. Catcher threads also get `join(timeout=5)`. Worst-case teardown is now ~25s with a logger warning, not indefinite.
Coordinated fix in every long-running `subprocess.Popen` that becomes `self.proc`:
- `perf_monitors/__init__.py` `Monitor.terminate()` — process-group SIGINT + escalating SIGKILL + bounded waits + thread joins with timeouts
- `perf_monitors/perfstat.py:96` (`PerfStat.run`) — add `start_new_session=True`
- `perf_monitors/topdown.py:187` (`IntelPerfSpect.run`) — same
- `perf_monitors/topdown.py:268` (`IntelPerfSpect3.run`) — same
- `perf_monitors/topdown.py:332` (`BasePerfUtil.run` — AMD collectors) — same
- `perf_monitors/topdown.py:505` (`ARMPerfUtil.run` — Grace) — same
Short-lived post-processing Popens (those followed immediately by `.wait()` with no concurrent reader) were left unchanged — they don't suffer from the hang because they're synchronous.
Reviewed By: YifanYuan3
Differential Revision: D1074269911 parent 920920c commit 7315161
3 files changed
Lines changed: 67 additions & 10 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
98 | 98 | | |
99 | 99 | | |
100 | 100 | | |
101 | | - | |
102 | | - | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
103 | 111 | | |
104 | 112 | | |
105 | 113 | | |
106 | | - | |
107 | | - | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
108 | 136 | | |
109 | | - | |
| 137 | + | |
110 | 138 | | |
111 | | - | |
| 139 | + | |
112 | 140 | | |
113 | 141 | | |
114 | 142 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
93 | 93 | | |
94 | 94 | | |
95 | 95 | | |
96 | | - | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
97 | 103 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
185 | 185 | | |
186 | 186 | | |
187 | 187 | | |
188 | | - | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
189 | 198 | | |
190 | 199 | | |
191 | 200 | | |
| |||
266 | 275 | | |
267 | 276 | | |
268 | 277 | | |
269 | | - | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
270 | 284 | | |
271 | 285 | | |
272 | 286 | | |
| |||
329 | 343 | | |
330 | 344 | | |
331 | 345 | | |
332 | | - | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
333 | 354 | | |
334 | 355 | | |
335 | 356 | | |
| |||
494 | 515 | | |
495 | 516 | | |
496 | 517 | | |
| 518 | + | |
| 519 | + | |
497 | 520 | | |
498 | 521 | | |
499 | 522 | | |
| |||
0 commit comments