Isolate the faulthandler Module Between Interpreters
Personne n'a encore pris cette issue.
- Langage dominant
- Python
- Étoiles
- 77.2k
- Forks
- 36k
- Métriques de merge des PR
- Métriques de PR en attente
Description
(See gh-100227.)
Currently the faulthandler module has some state in _PyRuntimeState, including objects, which is shared by all interpreters. Interpreters should be isolated from each other, for a variety of reasons (including the possibility of a per-interpreter GIL). Isolating the module will involve moving some of the state to PyInterpreterState (and, under per-interpreter GIL, guarding other state with a global lock).
Code Analysis:
(expand)
Signals
The module installs handlers for various signals.
(expand)
fatal:
SIGBUS- bus errorSIGILL- illegal instructionSIGFPE- floating point exceptionSIGABRT- abortSIGSEGV- segfault
"user":
- the 5 fatal signals
- others (up to
Py_NSIG)
handlers:
faulthandler_fatal_error(signum)faulthandler_exc_handler()(on Windows)faulthandler_user()
State
Fields
https://github.com/python/cpython/blob/main/Include/internal/pycore_faulthandler.h#L49-L86
https://github.com/python/cpython/blob/main/Include/internal/pycore_runtime.h#L146
raw
https://github.com/python/cpython/blob/62251c3da06eb4662502295697f39730565b1717/Include/internal/pycore_faulthandler.h#L49-L86
https://github.com/python/cpython/blob/62251c3da06eb4662502295697f39730565b1717/Include/internal/pycore_faulthandler.h#L36-L46
tables:
name |
type |
#ifdef |
notes |
|---|---|---|---|
fatal_error |
|||
. enabled |
bool |
"is faulthandler enabled?" | |
. file |
PyObject * |
only for keeping .fd alive |
|
. fd |
int |
||
. all_threads |
bool |
||
. interp |
PyInterpreterState * |
show only its threads the one that enabled faulthandler |
|
. exc_handler |
void * |
MS_WINDOWS |
|
name |
type |
#ifdef |
notes |
thread |
--- | ||
. file |
PyObject * |
only for keeping .fd alive |
|
. fd |
int |
defaults to sys.stderr |
|
. timeout_us |
PY_TIMEOUT_T |
||
. repeat |
bool |
||
. interp |
PyInterpreterState * |
show only its threads the one that requested the info |
|
. exit |
bool |
||
. header |
char * |
||
. header_len |
size_t |
||
. cancel_event |
PyThread_type_lock |
||
. running |
PyThread_type_lock |
||
name |
type |
#ifdef |
notes |
user_signals |
struct faulthandler_user_signal * |
FAULTHANDLER_USER |
a dynamically allocated array (Py_NSIG) |
user_signals[signum] |
--- | ||
. enabled |
bool |
||
. file |
PyObject * |
||
. fd |
int |
||
. all_threads |
bool |
||
. chain |
bool |
||
. previous |
_Py_sighandler_t |
||
. interp |
PyInterpreterState * |
show only its threads the one that added the handler |
|
name |
type |
#ifdef |
notes |
old_stack |
stack_t |
FAULTHANDLER_USE_ALT_STACK |
|
stack |
stack_t |
FAULTHANDLER_USE_ALT_STACK |
Usage
simple:
name |
context |
get |
set |
|---|---|---|---|
fatal_error |
|||
. enabled |
module | faulthandler_is_enabled() |
faulthandler_disable_py() |
| signal | faulthandler_fatal_error() |
||
| internal | faulthandler_enable()faulthandler_disable() |
faulthandler_enable()faulthandler_disable() |
|
. file |
module | faulthandler_traverse() |
faulthandler_py_enable()faulthandler_traverse() |
| internal | faulthandler_disable() |
faulthandler_disable() |
|
. fd |
module | ||
| signal | faulthandler_fatal_error()faulthandler_exc_handler() |
||
. all_threads |
module | faulthandler_py_enable() |
|
| signal | faulthandler_fatal_error()faulthandler_exc_handler() |
||
. interp |
module | faulthandler_py_enable() |
|
| internal | faulthandler_fatal_error()faulthandler_exc_handler() |
||
. exc_handler |
internal | faulthandler_enable()faulthandler_disable() |
faulthandler_enable()faulthandler_disable() |
name |
context |
get |
set |
thread |
|||
. file |
module | faulthandler_dump_traceback_later()faulthandler_traverse() |
faulthandler_dump_traceback_later()faulthandler_traverse() |
| internal | cancel_dump_traceback_later() |
cancel_dump_traceback_later() |
|
. fd |
|||
| module | faulthandler_dump_traceback_later() |
||
| thread | faulthandler_thread() |
||
. timeout_us |
module | faulthandler_dump_traceback_later() |
|
| thread | faulthandler_thread() |
||
. repeat |
module | faulthandler_dump_traceback_later() |
|
| thread | faulthandler_thread() |
||
. interp |
module | faulthandler_dump_traceback_later() |
|
| thread | faulthandler_thread() |
||
. exit |
module | faulthandler_dump_traceback_later() |
|
| thread | faulthandler_thread() |
||
. header |
module | faulthandler_dump_traceback_later() |
|
| thread | faulthandler_thread() |
||
| internal | cancel_dump_traceback_later() |
cancel_dump_traceback_later() |
|
. header_len |
module | faulthandler_dump_traceback_later() |
|
| thread | faulthandler_thread() |
||
. cancel_event |
module | faulthandler_dump_traceback_later() |
faulthandler_dump_traceback_later() |
| thread | faulthandler_thread() |
||
| internal | cancel_dump_traceback_later() |
||
. running |
module | faulthandler_dump_traceback_later() |
faulthandler_dump_traceback_later() |
| thread | faulthandler_thread() |
||
| internal | cancel_dump_traceback_later() |
||
name |
context |
get |
set |
user_signals |
module | faulthandler_register_py()faulthandler_unregister_py() |
faulthandler_register_py()faulthandler_traverse() |
| C-API | _PyFaulthandler_Fini() |
_PyFaulthandler_Fini() |
|
| signal | faulthandler_user() |
||
user_signals[signum] |
|||
. enabled |
module | faulthandler_register_py() |
faulthandler_register_py() |
| signal | faulthandler_user() |
||
| internal | faulthandler_unregister() |
faulthandler_unregister() |
|
. file |
module | faulthandler_register_py()faulthandler_traverse() |
faulthandler_register_py()faulthandler_traverse() |
| internal | faulthandler_unregister() |
faulthandler_unregister() |
|
. fd |
module | faulthandler_register_py() |
|
| signal | faulthandler_user() |
||
| internal | faulthandler_unregister() |
||
. all_threads |
module | faulthandler_register_py() |
|
| signal | faulthandler_user() |
||
. chain |
module | faulthandler_register_py() |
|
| signal | faulthandler_user() |
||
. previous |
module | faulthandler_register_py() |
|
| signal | faulthandler_user() |
||
| internal | faulthandler_unregister() |
||
. interp |
module | faulthandler_register_py() |
|
| signal | faulthandler_user() |
||
name |
context |
get |
set |
stack |
C-API | _PyFaulthandler_Init()_PyFaulthandler_Fini() |
|
| internal | faulthandler_enable()faulthandler_register()faulthandler_allocate_stack() |
||
old_stack |
C-API | _PyFaulthandler_Fini() |
modify data in complex fields:
name |
context |
calls |
|---|---|---|
fatal_error .fd |
signal | faulthandler_fatal_error() -> faulthandler_dump_traceback()faulthandler_fatal_error() -> _Py_DumpExtensionModules()faulthandler_exc_handler()faulthandler_exc_handler() -> _Py_DumpHexadecimal()faulthandler_exc_handler() -> faulthandler_dump_traceback() |
thread.fd |
thread | faulthandler_thread() -> _Py_write_noraise()faulthandler_thread() -> _Py_DumpTracebackThreads() |
thread .cancel_event |
module | faulthandler_dump_traceback_later() |
| C-API | _PyFaulthandler_Fini() |
|
| thread | faulthandler_thread() |
|
| internal | cancel_dump_traceback_later() |
|
thread .running |
module | faulthandler_dump_traceback_later() |
| thread | faulthandler_thread() |
|
| internal | cancel_dump_traceback_later() |
|
user_signals[signum] .fd |
signal | faulthandler_user() -> faulthandler_dump_traceback() |
stack |
C-API | _PyFaulthandler_Init()_PyFaulthandler_Fini() |
| internal | faulthandler_allocate_stack() |
|
old_stack |
internal | faulthandler_allocate_stack() -> sigaltstack() |
Guide de contribution
Ouvrir le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Piste de recherche
Commencez par Include/internal/pycore_faulthandler.h et Include/internal/pycore_runtime.h, puis suivez les points d’entrée listés tels que _PyFaulthandler_Init(), _PyFaulthandler_Fini(), faulthandler_enable() et faulthandler_user(). Déterminez à quel niveau de propriété, interpréteur ou global, appartient chaque champ partagé des tables d’état, et vérifiez que l’état de faulthandler est isolé sans perturber le comportement des gestionnaires de signaux.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Évaluation
- Stack technique
- c, python
- Domaine
- operating-systems
- Type d'issue
- Refactorisation
- Difficulté
- 5/5
- Temps estimé
- Plus d'une semaine
- Activité
- À l'abandon
- Clarté
- Plutôt claire
- Accessibilité débutants
- 25/100