Skip to content

import trio runs cc, ld and objdump on FreeBSD (find_library("pthread") in _thread_cache.py) #3538

Open

Description

@mbedworth

On FreeBSD, every import trio starts the C compiler, the linker and objdump. The cause is ctypes.util.find_library("pthread") in src/trio/_core/_thread_cache.py (line 54 on master).

CPython's find_library on FreeBSD first parses ldconfig -r. FreeBSD's threads library is registered there as -lthr.3 (/lib/libthr.so.3), and there's no -lpthread entry, so the lookup misses. It then falls back to _findLib_gcc(), which links a throwaway program with cc -Wl,-t ... -lpthread (this works because /usr/lib/libpthread.so is a symlink to libthr.so), and then runs objdump to read the soname. The answer is right (libthr.so.3), but it costs a toolchain run.

Reproduction (FreeBSD 15.1-RELEASE-p4, Python 3.13.15, trio 0.34.0):

$ truss -f -o /tmp/tr.out python3 -c "import trio"
$ grep -o 'execve("[^"]*"' /tmp/tr.out
execve("/sbin/ldconfig"
execve("/usr/bin/cc"
execve("/usr/bin/ld"
execve("/usr/bin/objdump"

The same happens with only ctypes.util.find_library("pthread"). By comparison, on the same machine:

find_library("pthread") -> libthr.so.3   execs: ldconfig, cc, ld, objdump
find_library("thr")     -> libthr.so.3   execs: ldconfig
ctypes.CDLL(None) has pthread_setname_np: True

Why it matters: OPNsense (a FreeBSD-based firewall) runs stock Python jobs, one of them every minute, that import dnspython's async resolver, which imports trio. On our firewall, process accounting counted 76 runs each of cc, ld.lld and objdump an hour (about 1,800 a day) on a box that otherwise never uses a toolchain.

Possible fixes, for you to judge:

  • On FreeBSD, look up thr first (it's found from ldconfig -r alone), or
  • try ctypes.CDLL(None) first: the process already links the threads library, and pthread_setname_np resolves from it, or
  • resolve the library lazily, the first time a thread name is set, instead of at import.

Activity

  1. abhishekacharya200 commented on Oct 12, 2026

    @abhishekacharya200

    Opened #3539, which takes your first suggestion: look up thr before pthread on FreeBSD, keeping the existing fallbacks.

  2. A5rocks commented on Oct 12, 2026

    @A5rocks
    Contributor

    Hmm, naively I would expect looking up thr to be bad (option 1), since we in particular want pthreads's interface. I'm not much of a C programmer though, so maybe it's always true that thr satisfies the pthreads interface?

  3. njsmith commented on Oct 12, 2026

    @njsmith
    Member
  4. A5rocks commented on Oct 12, 2026

    @A5rocks
    Contributor

    ctypes.CDLL(None).pthread_setname_np works at least for my Python installation on MacOS. Using that seems ideal, maybe with a fallback case for the long tail of platforms which might be weird.

  5. njsmith commented on Oct 12, 2026

    @njsmith
    Member
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions