Skip to content

_remote_debugging: get_child_pids() iterates all processes four times #156060

Description

@maurycy

Bug report

Bug description:

Found while trying to understand the gcmon performance in #155828 (comment).

We treat proc_listpids() as a number of PIDs:

int n_pids = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0);

int actual = proc_listpids(PROC_ALL_PIDS, 0, pid_list, buffer_size * sizeof(pid_t));

for (int i = 0; i < actual; i++) {

...but it returns a number of bytes:

https://github.com/apple-oss-distributions/xnu/blob/f6217f891ac0bb64f3d375211650a4c1ff8ca1ea/libsyscall/wrappers/libproc/libproc.c#L62-L73

sizeof(pid_t) == 4, so it does 4x times more work than it needs to be.

This was changed in #144648.

Reproduction

2026-08-19T18:53:44.066591000+0200 maurycy@gimel /Users/maurycy/src/github.com/maurycy/cpython (main f40043e*?) % ps axlww | wc -l
     996
2026-08-19T18:53:46.142930000+0200 maurycy@gimel /Users/maurycy/src/github.com/maurycy/cpython (main f40043e*?) % sudo dtrace -q -n 'pid$target::proc_pidinfo:entry { @ = count(); }' -c "./python.exe repro.py"

             3996

for

import _remote_debugging, os
_remote_debugging.get_child_pids(os.getpid(), recursive=True)

Fix

I believe the simplest fix should be along the lines of:

int n_pids = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0) / sizeof(pid_t);
...
int actual = proc_listpids(PROC_ALL_PIDS, 0, pid_list,
                            buffer_size * sizeof(pid_t)) / sizeof(pid_t);

(not exactly like that because proc_listpids() can return -1).

CPython versions tested on:

CPython main branch

Operating systems tested on:

macOS

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    OS-macextension-modulesC modules in the Modules dirtype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions