python / python/cpython

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

Aberta
#155,283 2 comentários 0 reações 0 responsáveis Ver no GitHub

Ninguém assumiu esta issue ainda.

extension-modules topic-ctypes type-crash
Linguagem predominante
Python
Estrelas
77.2k
Forks
35.9k
Métricas de merge de PRs
Métricas de PR pendentes

Descrição

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

Guia de contribuição

Abrir o guia de contribuição

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Direção de pesquisa

Comece com ctypes.util.find_library(), ctypes.util.dllist() e o _info_callback criado sob demanda descrito no relatório; em seguida, reproduza o exemplo mínimo de os.fork() no Linux com CPython 3.14. Rastreie o encerramento do processo filho pelo caminho de desalocação de libffi e _ctypes mostrado. O trabalho estará concluído quando o processo filho sair sem SIGABRT depois que o callback tiver sido criado antes de fork().

Escrita pelo modelo de indexação a partir do texto da issue.

Avaliação

Stack de tecnologia
python
Domínio
backend, operating-systems
Tipo de issue
Bug
Dificuldade
4/5
Tempo estimado
3-5 dias
Status de atividade
Pouca atividade
Clareza
Razoavelmente clara
Facilidade para iniciantes
38/100

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.