cleanupDir(dirPath: string): Promise<void>
Kills all surviving processes that reference dirPath (checked via cwd, cmdline,
and open file descriptors), then retries fs.rm() until it succeeds or a 5-second
deadline expires. Re-scans /proc on each failed rm() attempt to catch processes
that appear after the initial scan (e.g. late-forked Chrome helpers).
Deliberately does NOT wait for killed processes to fully leave the process table (no killAndAwait). kill(pid, 0) succeeds for zombie processes (FDs already released) and for D-state processes (SIGKILL queued but not yet delivered), so polling it can stall indefinitely on a loaded CI machine while rm() could already succeed. Instead, rm() itself is the authoritative check: it fails while FDs are held and succeeds once they are released, regardless of how far the process-table cleanup has progressed.
Linux-only: falls back to a single best-effort rm() on other platforms.
import * as Chrome from './index.ts'; // Defined, not invoked: a real call SIGKILLs FD holders and rm()s the directory. async function reapUserDataDir(userDataDir: string) { await Chrome.cleanupDir(userDataDir); // resolves once gone, or after the 5s deadline }