Summary:
- C-API takes opaque context type as first arg
- context is as specific as possible
- separate Py_Main() from runtime initialization
- separate global init from interpreter init
- explicit enabling/disabling runtime components
(expand)
initialization:
(expand)
-
update config from env vars & CLI
-
init hash randomization
-
copy
PyImport_Initab -
allow creating interpreters
-
initialize main interpreter (part 1)
- create interpreter
- copy
PyConfig
-
set
_PyRuntime->gilstate.autoInterpreterState -
initialize main interpreter (part 2)
- set feature flags (from
PyInterpreterConfig) - init obmalloc state
- create main thread state (and bind)
- initialize GIL (and take it)
- set feature flags (from
-
init global
floatstate -
initialize main interpreter (part 3)
- init interned str dict
-
init statically defined
strobjects -
init global
strstate -
initialize main interpreter (part 4)
-
init interned str dict
-
init
interp->dtoa.p5s -
init (almost) all the builtin types
-
init the typevar heap types (and cache them)
-
init
Int_InfoType -
str: initEncodingMapType -
str: initPyFieldNameIter_Type -
str: initPyFormatterIter_Type -
initialize
FloatInfoType -
init the static builtin exception types
-
preallocate some memory errors
-
init
interp->exc_state.errnomap -
init
UnraisableHookArgsType -
set
PyContextToken_Type.MISSING -
init
_PyExc_InterpreterError -
init
_PyExc_InterpreterNotFoundError -
init
interp->warnings.filters -
init
interp->warnings.once_registry -
init
interp->warnings.default_action -
init
interp->atexit -
init
sysmodule 1. initsys.modules2. createsys3. setinterp->sysdict4. setinterp->sysdict_copy5. setsys.modules6. setsys.stderr,sys.__stderr__(preliminary) 7. setsys.displayhook,sys.__displayhook__8. setsys.excepthook,sys.__excepthook__9. setsys.breakpointhook,sys.__breakpointhook__10. setsys.unraisablehook,sys.__unraisablehook__11. setsys.version12. setsys.hexversion13. setsys._git14. setsys._framework15. setsys.api_version16. setsys.copyright17. setsys.platform18. setsys.maxsize19. setsys.float_info20. setsys.int_info21. initHash_InfoType22. setsys.hash_info23. setsys.maxunicode24. setsys.builtin_module_names25. setsys.stdlib_module_names26. setsys.byteorder27. setsys.dllhandle28. setsys.winver29. setsys.abiflags30. initVersionInfoType31. setsys.version_info32. initImplementationType33. setsys.implementation34. initFlagsType35. init and setsys.flags36. initWindowsVersionType37. setsys._vpath38. setsys.float_repr_style39. setsys.thread_info40. initAsyncGenHooksType41. initEmscriptenInfoType42. setsys._emscripten_info43. setsys.meta_path44. setsys.path_importer_cache45. setsys.path_hooks46._PyImport_FixupBuiltin("sys")47. setsys.monitoring -
initialize the "builtins" module 1.
_PyBuiltin_Init()2._PyImport_FixupBuiltin("builtins")3. setinterp->callable_cache.isinstance4. setinterp->callable_cache.len5. setinterp->callable_cache.list_append6. setinterp->callable_cache.object__getattribute__7._PyBuiltins_AddExceptions()8. setinterp->builtins_copy9._PyImport_InitDefaultImportFunc() -
init the global XID registry
-
init the XID registry
-
init "core" import system 1. load
_frozen_importlib(importlib._bootstrap) 2. setinterp->imports.importlib3. loadimp4. call_frozen_imporlib._install() -
_PyConfig_InitImportConfig() -
interpreter_update_config() -
_PyImport_InitExternal() -
_PyFaulthandler_Init() -
_PyUnicode_InitEncodings() -
_PySignal_Init() -
_PyTraceMalloc_Start() -
_PyPerfTrampoline_SetCallbacks() -
_PyPerfTrampoline_Init() -
init_sys_streams() -
init_set_builtins_open() -
run_presite() -
add_main_module() -
PyImport_ImportModule("warnings")(validatessys.warnoptions?) -
init_import_site() -
on Windows,
emit_stderr_warning_for_legacy_locale() -
created and set the ceval optimizer
finalization:
(expand)
- ...
responsibilities of "main" interpreter:
- ...
"main" interpreter possibilities:
- the first one given to the user (status quo)
- the active one in the main thread
- not exposed to users
- users must explicitly ask for it
- explicitly declared by the user
initialization:
(expand)
-
create interpreter
-
copy
PyConfigfrom calling interpreter (or main) -
set feature flags (from
PyInterpreterConfig) -
init obmalloc state
-
create (temp) thread state (and bind)
-
initialize GIL (and take it)
-
init interned str dict
-
init
interp->dtoa.p5s -
init (almost) all the non-exc static builtin types
-
init the typevar heap types (and cache them)
-
init
Int_InfoType -
str: initEncodingMapType -
str: initPyFieldNameIter_Type -
str: initPyFormatterIter_Type -
initialize
FloatInfoType -
init the static builtin exception types
-
init
interp->exc_state.errnomap -
init
UnraisableHookArgsType -
init
_PyExc_InterpreterError -
init
_PyExc_InterpreterNotFoundError -
init
interp->warnings.filters -
init
interp->warnings.once_registry -
init
interp->warnings.default_action -
init
interp->atexit -
init
sysmodule -
init
sys.modules -
create
sys -
set
interp->sysdict -
set
interp->sysdict_copy -
set
sys.modules -
set
sys.stderr,sys.__stderr__(preliminary) -
set
sys.displayhook,sys.__displayhook__ -
set
sys.excepthook,sys.__excepthook__ -
set
sys.breakpointhook,sys.__breakpointhook__ -
set
sys.unraisablehook,sys.__unraisablehook__ -
set
sys.version -
set
sys.hexversion -
set
sys._git -
set
sys._framework -
set
sys.api_version -
set
sys.copyright -
set
sys.platform -
set
sys.maxsize -
set
sys.float_info -
set
sys.int_info -
init
Hash_InfoType -
set
sys.hash_info -
set
sys.maxunicode -
set
sys.builtin_module_names -
set
sys.stdlib_module_names -
set
sys.byteorder -
set
sys.dllhandle -
set
sys.winver -
set
sys.abiflags -
init
VersionInfoType -
set
sys.version_info -
init
ImplementationType -
set
sys.implementation -
init
FlagsType -
init and set
sys.flags -
init
WindowsVersionType -
set
sys._vpath -
set
sys.float_repr_style -
set
sys.thread_info -
init
AsyncGenHooksType -
init
EmscriptenInfoType -
set
sys._emscripten_info -
set
sys.meta_path -
set
sys.path_importer_cache -
set
sys.path_hooks -
_PyImport_FixupBuiltin("sys") -
set
sys.monitoring -
initialize the "builtins" module
-
_PyBuiltin_Init() -
_PyImport_FixupBuiltin("builtins") -
set
interp->callable_cache.isinstance -
set
interp->callable_cache.len -
set
interp->callable_cache.list_append -
set
interp->callable_cache.object__getattribute__ -
_PyBuiltins_AddExceptions() -
set
interp->builtins_copy -
_PyImport_InitDefaultImportFunc() -
init the global XID registry
-
init the XID registry
-
init "core" import system
-
load
_frozen_importlib(importlib._bootstrap) -
set
interp->imports.importlib -
load
imp -
call
_frozen_imporlib._install() -
_PyConfig_InitImportConfig() -
interpreter_update_config() -
_PyImport_InitExternal() -
_PyUnicode_InitEncodings() -
init_sys_streams() -
init_set_builtins_open() -
run_presite() -
add_main_module() -
init_import_site() -
set
sys.path[0](
finalization:
(expand)
- ...
sources:
- docs
- sys modules
PyConfig- builtin modules
- stdlib modules
- C-API
- Steve's rings & layers proposal (specifically, the layers)
- opt stdlib -> req stdlib -> platform adaption -> core
components:
(expand)
- build info
- CLI (main)
- core (global)
- builtin objects (singletons, types, instances)
- exception machinery
- warnings machinery
- debug utils
- core (interp)
- import system
- builtin modules
- frozen modules
- "external" modules
- sys.path
- "site" (and user site)
- Python compiler
- Python bytecode interpreter
- profiling
- tracing
- multiple interpreters (cross-interpreter)
- import system
- platform
- locale/encoding
- allocators
- hash
- cryptographic RNG
- filesystem
- stdio
- signals
- threads
- fork
- subprocesses
- network
- users
- security
- devices
- virtualization
- stdlib (required)
- stdlib (optional)
- full set of text codecs
- ...
A "context" is essentially an opaque handle to some runtime context. The idea is that all CPython's API take a specific context type as its first argument.
(expand for code)
/* A high-level brain dump of a possible top-level CPython API. */
/****************************/
/* CPython's main() */
/****************************/
typedef struct main_config {
//PyRuntime_base_config_t runtimecfg,
//PyInterpreter_base_config_t interpcfg,
//...
} PyMain_config_t;
typedef struct main_args {
int argc;
wchar_t **argv;
PyMain_config_t config;
} PyMain_args_t;
struct main_context;
typedef struct main_context * PyMain_context_t;
PyAPI_FUNC(void) PyMain_context_zero(PyMain_context_t *);
PyAPI_FUNC(int) PyMain_context_is_zero(PyMain_context_t);
PyAPI_FUNC(Py_error_t) PyMain_Initialize(
PyMain_args_t args,
PyMain_context_t *p_res);
PyAPI_FUNC(Py_error_t) PyMain_Finalize(PyMain_context_t);
/****************************/
/* global runtime */
/****************************/
// XXX Distinct init config vs. fini config?
// XXX PyRuntime_config_t?
typedef struct runtime_base_config {
//...
} PyRuntime_base_config_t;
struct runtime_base_ctx;
typedef struct runtime_base_ctx * PyRuntime_base_context_t;
/* For now, this fails if a runtime has already been initialized. */
PyAPI_FUNC(Py_error_t) PyRuntime_Initialize(
PyRuntime_base_config_t *cfg,
PyRuntime_base_context_t *p_res);
/* This fails if the base context has un-finalized components. */
PyAPI_FUNC(Py_error_t) PyRuntime_Finalize(PyRuntime_base_context_t);
/****************************/
/* global components */
/****************************/
/* signals */
struct runtime_signals_ctx;
typedef struct runtime_signals_ctx * PyRuntime_signals_context_t;
PyAPI_FUNC(Py_error_t) PyRuntime_InstallSignalHandlers(
PyRuntime_base_context_t runtime,
PyInterpreter_thread_context_t *main,
PyRuntime_signals_context_t *p_res);
PyAPI_FUNC(Py_error_t) PyRuntime_UninstallSignalHandlers(
PyRuntime_signals_context_t);
/* ... */
//typedef ... PyRuntime_XXX_context_t;
//
//PyAPI_FUNC(Py_error_t) PyRuntime_EnableXXX(
// PyRuntime_base_context_t base,
// PyRuntime_XXX_config_t *cfg.
// PyRuntime_XXX_context_t *p_res);
//PyAPI_FUNC(Py_error_t) PyRuntime_DisableXXX(PyRuntime_XXX_context_t);
/****************************/
/* interpreter runtime */
/****************************/
// XXX Distinct init config vs. fini config?
// XXX PyInterpreter_config_t?
typedef struct interp_base_config {
//...
} PyInterpreter_base_config_t;
struct interp_base_ctx;
typedef struct interp_base_ctx * PyInterpreter_base_context_t;
struct interp_combined_ctx;
typedef struct interp_combined_ctx * PyInterpreter_context_t;
PyAPI_FUNC(Py_error_t) PyInterpreter_Initialize(
PyRuntime_base_context_t interp,
PyInterpreter_base_config_t *cfg,
PyInterpreter_base_context_t *p_res);
PyAPI_FUNC(Py_error_t) PyInterpreter_Finalize(PyInterpreter_base_config_t);
PyAPI_FUNC(Py_error_t) PyInterpreter_GetContext(
PyInterpreter_base_context_t *interp,
PyInterpreter_context_t *p_res);
PyAPI_FUNC(Py_error_t) PyInterpreter_GetBaseContext(
PyInterpreter_context_t *interp,
PyInterpreter_base_context_t *p_res);
/****************************/
/* interpreter components */
/****************************/
/* compiler */
struct interp_compiler_ctx;
typedef struct interp_compiler_ctx * PyInterpreter_compiler_context_t;
PyAPI_FUNC(Py_error_t) PyInterpreter_EnableCompiler(
PyInterpreter_base_context_t *interp,
PyInterpreter_compiler_context_t ctx,
const char *str,
const char *filename,
int start,
PyObject **p_res);
/* bytecode interpreter */
struct interp_exec_ctx;
typedef struct interp_exec_ctx * PyInterpreter_exec_context_t;
PyAPI_FUNC(Py_error_t) PyEval_EvalCode(
PyInterpreter_exec_context_t ctx,
PyObject *co,
PyObject *globals,
PyObject *locals,
PyObject **p_res);
/* multi-threading */
struct interp_threading_ctx;
typedef struct interp_threading_ctx * PyInterpreter_threading_context_t;
PyAPI_FUNC(Py_error_t) PyInterpreter_EnableMultiThreading(
PyInterpreter_base_context_t *interp,
PyInterpreter_threading_context_t *p_res);
PyAPI_FUNC(Py_error_t) PyInterpreter_DisableMultiThreading(
PyInterpreter_threading_context_t)
struct thread_nonlocal_ctx;
typedef struct thread_nonlocal_ctx * PyThread_nonlocal_context_t;
PyAPI_FUNC(Py_error_t) PyThread_Start(
PyInterpreter_threading_context_t ctx,
void (*func)(void *),
void *arg,
PyThread_nonlocal_context_t *p_res);
PyAPI_FUNC(Py_error_t) PyThread_Join(PyThread_nonlocal_context_t);
/****************************/
/* interpreter current thread */
/****************************/
struct interp_thread_ctx;
typedef struct interp_thread_ctx * PyInterpreter_thread_context_t;
PyAPI_FUNC(Py_error_t) PyInterpreter_BindThread(
PyInterpreter_base_context_t *interp,
PyInterpreter_thread_context_t *p_res);
PyAPI_FUNC(Py_error_t) PyInterpreter_UnbindThread(
PyInterpreter_thread_context_t);
/****************************/
/* high-level execution */
/****************************/
struct interp_main_ctx;
typedef struct interp_main_ctx * PyInterpreter_main_context_t;
PyAPI_FUNC(Py_error_t) PyInterpreter_SetMain(
PyThread_base_context_t interp,
PyInterpreter_main_context_t *p_res);
PyAPI_FUNC(Py_error_t) PyInterpreter_UnsetMain(
PyInterpreter_main_context_t ctx);(expand for code)
/* A high-level brain dump of a possible top-level CPython API. */
/****************************/
/* common */
/****************************/
//struct error_value {
// int code;
// ...
//};
//typedef struct error_value * Py_error_t;
typedef int Py_error_t;
PyAPI_FUNC(void) Py_error_zero(&Py_error_t);
PyAPI_FUNC(int) Py_error_is_zero(Py_error_t);
PyAPI_FUNC(int) Py_GetErrorReturnCode(Py_error_t);
PyAPI_FUNC(void) Py_GetErrorUTF8(Py_error_t, char *buf, size_t bufsize);
//PyAPI_FUNC(void) Py_GetErrorText(Py_error_t, wchar_t *buf, size_t bufsize);
PyAPI_FUNC(int) Py_HandleError(Py_error_t);
/****************************/
/* CPython's main() */
/****************************/
PyAPI_FUNC(int) PyMain_HandleError(Py_error_t);
PyAPI_FUNC(int) Py_Main(PyMain_context_t);
/****************************/
/* global runtime */
/****************************/
// API that takes a PyRuntime_base_context_t.
/****************************/
/* global components */
/****************************/
// API that takes a component-specific context argument.
/****************************/
/* interpreter runtime */
/****************************/
// API that takes a PyInterpreter_base_context_t argument.
// API that takes a PyInterpreter_context_t argument.
/****************************/
/* interpreter components */
/****************************/
// API that takes a component-specific context argument.
/* compiler */
PyAPI_FUNC(Py_error_t) Py_CompileString(
PyInterpreter_compiler_context_t ctx,
const char *str,
const char *filename,
int start,
PyObject **p_res);
/* bytecode interpreter */
PyAPI_FUNC(Py_error_t) PyEval_EvalCode(
PyInterpreter_exec_context_t ctx,
PyObject *co,
PyObject *globals,
PyObject *locals,
PyObject **p_res);
/****************************/
/* interpreter current thread */
/****************************/
// API that takes a PyThread_context_t argument.
/****************************/
/* high-level execution */
/****************************/
PyAPI_FUNC(Py_error_t) PyRun_SimpleString(
PyInterpreter_main_context_t ctx,
const char *command);
// ...Rough implementations of the existing C-API:
(expand for code)
extern PyStatus PyStatus_FromError(Py_error_t);
/****************************/
/* Py_Main() */
/****************************/
int
PyLegacy_Main(int argc, wchar_t **argv)
{
}
int
PyLegacy_BytesMain(int argc, char **argv)
{
}
/****************************/
/* Py_Initialize() */
/****************************/
struct interp_contexts {
PyInterpreter_base_context_t base;
PyInterpreter_thread_context_t main;
PyInterpreter_threading_context_t threading;
};
static PyStatus
legacy_interpreter_init(PyRuntime_interpreters_context_t interpreters,
PyInterpreter_base_config_t cfg,
struct interp_contexts *contexts)
{
Py_error_t err;
err = PyInterpreter_Initialize(interpreters, &cfg, &contexts->interp);
if (!Py_error_is_zero(err)) {
return PyStatus_FromError(err);
}
err = PyInterpreter_BindThread(interp, &contexts->main);
if (!Py_error_is_zero(err)) {
(void)PyInterpreter_Finalize(contexts->interp);
return PyStatus_FromError(err);
}
err = PyInterpreter_EnableMultiThreading(interp, &contexts->threading);
if (!Py_error_is_zero(err)) {
(void)PyInterpreter_Unbind(contexts->main);
(void)PyInterpreter_Finalize(contexts->interp);
return PyStatus_FromError(err);
}
return _PyStatus_OK();
}
static PyStatus
legacy_interpreter_fini_components(struct interp_contexts *contexts)
{
if (!PyInterpreter_threading_context_is_zero(contexts->threading)) {
(void)PyInterpreter_DisableMultiThreading(threading);
if (!PyInterpreter_threading_context_is_zero(contexts->main)) {
assert(PyThread_IsCurrent(contexts->main));
PyThread_WaitForOtherThreads(threading, contexts->main);
}
}
// pending calls
// PyAtExit_Call()
// delete all other thread states
PyInterpreter_Unbind(contexts->main);
PyInterpreter_Finalize(contexts->interp);
}
static struct interp_contexts main_interp;
PyStatus
PyLegacy_InitializeFromConfig(const PyConfig *config)
{
PyStatus status;
Py_error_t err;
// Initialize the runtime.
PyRuntime_base_config_t cfg_runtime = {
// Derived from config.
};
PyRuntime_base_context_t runtime;
err = PyRuntime_Initialize(&cfg_runtime, &runtime);
if (!Py_error_is_zero(err)) {
return PyStatus_FromError(err);
}
PyRuntime_interpreters_context_t interpreters;
err = PyRuntime_EnableSingleInterpreter(runtime, &interpreters);
if (!Py_error_is_zero(err)) {
}
// Initialize the the main interpreter
// (and leave the main thread context in place).
PyInterpreter_base_config_t cfg_interp = {
// ...
};
status = legacy_interpreter_init(interpreters, &cfg_interp, &main_interp);
if (_PyStatus_EXCEPTION(status)) {
return status;
}
// The main thread does special stuff.
PyRuntime_signals_context_t signals;
err = PyRuntime_InstallSignalHandlers(runtime, &main_interp.main, &signals);
if (!Py_error_is_zero(err)) {
(void)PyRuntime_DisableInterpreters(interpreters);
(void)legacy_interpreter_fini(&main_interp);
(void)PyRuntime_Finalize(runtime);
return PyStatus_FromError(err);
}
err = PyRuntime_EnableMultipleInterpreters(interpreters);
if (!Py_error_is_zero(err)) {
(void)PyRuntime_UninstallSignalHandlers(signals);
(void)PyRuntime_DisableInterpreters(interpreters);
(void)legacy_interpreter_fini(&main_interp);
(void)PyRuntime_Finalize(runtime);
return PyStatus_FromError(err);
}
// ...
return _PyStatus_OK();
}
int
PyLegacy_FinalizeEx(void);
{
int status = 0;
Py_error_t err;
PyRuntime_combined_context_t combined;
PyLegacy_GetRuntimeContext(&combined);
PyRuntime_base_context_t runtime;
PyRuntime_GetBaseContext(combined, &runtime);
if (!PyThread_IsCurrent(main_interp.main)) {
// XXX error!
return -1;
}
// ...
PyRuntime_interpreters_context_t interpreters;
PyRuntime_GetInterpretersContext(combined, &interpreters);
err = PyRuntime_DisableInterpreters(interpreters);
if (!Py_error_is_zero(err)) {
status = -1;
}
err = PyRuntime_FinalizeOtherInterpreters(interpreters, main_interp.base);
//err = legacy_finalize_other_interpreters(interpreters, main_interp.base);
if (!Py_error_is_zero(err)) {
status = -1;
}
PyRuntime_signals_context_t signals;
PyRuntime_GetSignalsContext(combined, &signals);
err = PyRuntime_UninstallSignalHandlers(signals);
if (!Py_error_is_zero(err)) {
status = -1;
}
err = legacy_interpreter_fini(&main_interp);
if (!Py_error_is_zero(err)) {
status = -1;
}
err = PyRuntimeFinalize(runtime);
if (!Py_error_is_zero(err)) {
status = -1;
}
return status;
}Fresh examples:
(expand for code)
extern int decode_argv(const int argc, const char **argv, const char *encoding,
wchar_t **p_res);
static int
main1(int argc, char **argv)
{
PyMain_args_t args = {
.argc = argc,
.argv = NULL,
.config = {
// ...
},
}
if (decode_argv(argc, argv, &args.argv, "utf-8") < 0) {
return 1;
}
PyMain_context_t ctx;
Py_error_t err = PyMain_Initialize(&cfg, &ctx);
int rc = PyMain_HandleError(err);
if (rc != 0) {
return rc;
}
rc = Py_Main(ctx);
err = PyMain_Finalize(ctx);
(void)PyMain_HandleError(err);
return rc;
}
static int
main2(int argc, char **argv)
{
int rc;
Py_error_t err;
Py_error_zero(err);
PyRuntime_base_context_t runtime;
PyRuntime_signals_context_t signals1;
PyInterpreter_base_context_t interp;
PyInterpreter_thread_context_t main;
PyRuntime_signals_context_t signals2;
PyInterpreter_threading_context_t threading;
PyThread_nonlocal_context_t thread;
PyRuntime_base_context_zero(&runtime);
PyRuntime_signals_context_zero(&signals1);
PyInterpreter_base_context_zero(&interp);
PyInterpreter_thread_context_zero(&main);
PyRuntime_signals_context_zero(&signals2);
PyInterpreter_threading_context_zero(&threading);
PyThread_nonlocal_context_zero(&thread);
PyRuntime_base_config_t cfg_runtime = {
// ...
};
err = PyRuntime_Initialize(&cfg_runtime, &runtime);
// ...or that could be named Py_Initialize()...
rc = Py_HandleError(err);
if (rc != 0) {
goto finally;
}
/* At this point we can use the runtime without an interpreter. */
err = PyRuntime_InstallSignalHandlers(runtime, NULL, &signals1);
// ...or that could be named PyMain_InstallSignalHandlers()...
rc = Py_HandleError(err);
if (rc != 0) {
goto finally;
}
PyInterpreter_base_config_t cfg_interp = {
// ...
};
err = PyInterpreter_Initialize(runtime, &cfg_interp, &interp);
// ...or that could be named Py_NewInterpreter()...
rc = Py_HandleError(err);
if (rc != 0) {
goto finally;
}
err = PyInterpreter_BindThread(interp, &main);
rc = Py_HandleError(err);
if (rc != 0) {
goto finally;
}
if (PyRuntime_signals_is_zero(signals1)) {
err = PyRuntime_InstallSignalHandlers(runtime, &main, &signals2);
rc = Py_HandleError(err);
if (rc != 0) {
goto finally;
}
}
// Start a subthread.
err = PyInterpreter_EnableMultiThreading(interp, &threading);
rc = Py_HandleError(err);
if (rc != 0) {
goto finally;
}
err = PyThread_Start(func, arg, &thread);
rc = Py_HandleError(err);
if (rc != 0) {
goto finally;
}
/* Manage the thread using the "non-local" handle. */
/* Do more stuff in the current thread. */
// ...
rc = 0;
finally:
if (!PyThread_nonlocal_context_is_zero(thread)) {
err = PyInterpreter_Unbind(main);
int rc2 = Py_HandleError(err);
rc = rc == 0 ? rc2 : rc;
}
if (!PyInterpreter_thread_context_is_zero(main)) {
err = PyInterpreter_Unbind(main);
int rc2 = Py_HandleError(err);
rc = rc == 0 ? rc2 : rc;
}
if (!PyInterpreter_threading_context_is_zero(threading)) {
err = PyInterpreter_DisableMultiThreading(threading);
int rc2 = Py_HandleError(err);
rc = rc == 0 ? rc2 : rc;
}
if (!PyInterpreter_signals_context_is_zero(signals2)) {
err = PyInterpreter_UninstallSignalHandlers(signals2);
int rc2 = Py_HandleError(err);
rc = rc == 0 ? rc2 : rc;
}
if (!PyInterpreter_base_context_is_zero(interp)) {
err = PyInterpreter_Finalize(interp);
// ...or that could be named Py_EndInterpreter()...
int rc2 = Py_HandleError(err);
rc = rc == 0 ? rc2 : rc;
}
if (!PyRuntime_signals_context_is_zero(signals1)) {
err = PyRuntime_UninstallSignalHandlers(signals1);
int rc2 = Py_HandleError(err);
rc = rc == 0 ? rc2 : rc;
}
if (!PyRuntime_base_context_is_zero(runtime)) {
err = PyRuntime_Finalize(runtime);
// ...or that could be named Py_Finalize()...
int rc2 = Py_HandleError(err);
rc = rc == 0 ? rc2 : rc;
}
return rc;
}
static int
main3(int argc, char **argv)
{
}
int
main(int argc, char **argv)
{
return main1(argc, argv);
//return main2(argc, argv);
//return main3(argc, argv);
}