python / python/cpython

`ctypes.util._info_callback` (dl_iterate_phdr) closure causes SIGABRT in child after `os.fork()`

Open
#155,283 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

extension-modules topic-ctypes type-crash
Dominant language
Python
Stars
77.2k
Forks
35.9k
PR merge metrics
PR metrics pending

Description

Crash report

What happened?

ctypes.util._info_callback (dl_iterate_phdr) closure causes SIGABRT in child after os.fork()

Versions: Python 3.14.5, Linux x86_64, libffi 3.4.x (/lib64/libffi.so.8)

Hi all,
I have updated my code library from Python3.9 to 3.14. I have noticed that stopping my Python service produced core dumps. My service has a parent which forks multiple children which use scikit-learn.

I could reproduce a minimal running code with a coredump. Sorry, I am not sure, whether it is threadpoolctl or CPython issue. Thus, I opened an issue at threadpoolctl as well.

Below you will find the structured output summarized by our glorious AI overlords.

Thanks!

Problem

If ctypes.util.find_library() (or ctypes.util.dllist()) is called in a
parent process — which lazily creates and caches the module-level
ctypes.CFUNCTYPE closure ctypes.util._info_callback used by the
dl_iterate_phdr()-based lookup added in gh-119349 — and the process then
calls os.fork(), the forked child reliably SIGABRTs when it later exits
via sys.exit()/Py_Finalize():

abort
dlfree.cold (libffi.so.8)
CThunkObject_dealloc (_ctypes.cpython-314-x86_64-linux-gnu.so)
_Py_Dealloc
dict_dealloc
_Py_Dealloc
PyCData_clear (_ctypes)
PyCFuncPtr_dealloc (_ctypes)
_Py_Dealloc
insertdict.isra.0
_PyModule_ClearDict
finalize_modules
_Py_Finalize
Py_Exit
handle_system_exit
...
Py_RunMain
Py_BytesMain

The abort is inside libffi's own private closure allocator (dlfree in
libffi.so.8), not glibc's malloc (confirmed via MALLOC_CHECK_=3, which
had no effect).

Minimal repro
import os, sys, signal, time
from ctypes.util import find_library

find_library("c")  # creates ctypes.util._info_callback in the parent

def child():
    signal.signal(signal.SIGTERM, lambda s, f: sys.exit(0))
    find_library("c")
    time.sleep(30)

pid = os.fork()
if pid == 0:
    child()
else:
    time.sleep(3)
    os.kill(pid, signal.SIGTERM)
    os.waitpid(pid, 0)

python3.14 repro.pyAborted (core dumped) in the child.

Notes:

  • Calling find_library() alone (no fork) does not crash.
  • os.fork() alone (no prior ctypes.util activity) does not crash.
  • Only the combination — closure created pre-fork, then freed at shutdown
    in the child — reproduces it.
  • This did not occur on Python 3.9, since the dl_iterate_phdr-based
    ctypes.util implementation (gh-119349) did not exist there.
CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Output from running 'python -VV' on the command line:

No response

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with ctypes.util.find_library(), ctypes.util.dllist(), and the lazily created _info_callback described in the report, then reproduce the minimal os.fork() example on Linux with CPython 3.14. Trace the child’s shutdown through the shown libffi and _ctypes deallocation path. Done means the child exits without SIGABRT after the callback was created before fork().

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend, operating-systems
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.