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
float
state -
initialize main interpreter (part 3)
- init interned str dict
-
init statically defined
str
objects -
init global
str
state -
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
sys
module 1. initsys.modules
2. createsys
3. setinterp->sysdict
4. setinterp->sysdict_copy
5. setsys.modules
6. 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.version
12. setsys.hexversion
13. setsys._git
14. setsys._framework
15. setsys.api_version
16. setsys.copyright
17. setsys.platform
18. setsys.maxsize
19. setsys.float_info
20. setsys.int_info
21. initHash_InfoType
22. setsys.hash_info
23. setsys.maxunicode
24. setsys.builtin_module_names
25. setsys.stdlib_module_names
26. setsys.byteorder
27. setsys.dllhandle
28. setsys.winver
29. setsys.abiflags
30. initVersionInfoType
31. setsys.version_info
32. initImplementationType
33. setsys.implementation
34. initFlagsType
35. init and setsys.flags
36. initWindowsVersionType
37. setsys._vpath
38. setsys.float_repr_style
39. setsys.thread_info
40. initAsyncGenHooksType
41. initEmscriptenInfoType
42. setsys._emscripten_info
43. setsys.meta_path
44. setsys.path_importer_cache
45. setsys.path_hooks
46._PyImport_FixupBuiltin("sys")
47. setsys.monitoring
-
initialize the "builtins" module 1.
_PyBuiltin_Init()
2._PyImport_FixupBuiltin("builtins")
3. setinterp->callable_cache.isinstance
4. setinterp->callable_cache.len
5. setinterp->callable_cache.list_append
6. setinterp->callable_cache.object__getattribute__
7._PyBuiltins_AddExceptions()
8. setinterp->builtins_copy
9._PyImport_InitDefaultImportFunc()
-
init the global XID registry
-
init the XID registry
-
init "core" import system 1. load
_frozen_importlib
(importlib._bootstrap) 2. setinterp->imports.importlib
3. loadimp
4. 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
PyConfig
from 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
sys
module -
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);
}