pidfd_create starts one detached thread per pidfd, which blocks in kevent() waiting for NOTE_EXIT on the target. pidfd_cleanup only closes write_end and marks the entry inactive, so the thread stays parked until the target exits, even though nothing reads the result any more.
A guest that opens and closes pidfds in a loop on a long-lived child keeps one host thread per iteration. The growth can be seen with ps -M <elfuse pid> while such a loop runs.
Two ways to fix it:
- Register an
EVFILT_USER event on each monitor's kqueue and trigger it from pidfd_cleanup, so the thread wakes and exits. This is a small change and keeps one thread per pidfd.
- Replace the per-pidfd threads with one shared monitor thread and one kqueue watching every target. This removes the per-pidfd thread entirely but is a larger rewrite of
src/syscall/proc-pidfd.c.
I would start with the first.
Found while reviewing #399.
pidfd_createstarts one detached thread per pidfd, which blocks inkevent()waiting forNOTE_EXITon the target.pidfd_cleanuponly closeswrite_endand marks the entry inactive, so the thread stays parked until the target exits, even though nothing reads the result any more.A guest that opens and closes pidfds in a loop on a long-lived child keeps one host thread per iteration. The growth can be seen with
ps -M <elfuse pid>while such a loop runs.Two ways to fix it:
EVFILT_USERevent on each monitor's kqueue and trigger it frompidfd_cleanup, so the thread wakes and exits. This is a small change and keeps one thread per pidfd.src/syscall/proc-pidfd.c.I would start with the first.
Found while reviewing #399.