| 43 | }; |
| 44 | |
| 45 | void PyModuleRegistry::init() |
| 46 | { |
| 47 | std::lock_guard locker(lock); |
| 48 | |
| 49 | // Set up global python interpreter |
| 50 | #define WCHAR(s) L ## #s |
| 51 | PyConfig py_config; |
| 52 | // do not enable isolated mode, otherwise we would not be able to have access |
| 53 | // to the site packages. since we cannot import any module before initializing |
| 54 | // the interpreter, we would not be able to use "site" module for retrieving |
| 55 | // the path to site packager. we import "site" module for retrieving |
| 56 | // sitepackages in Python < 3.8 though, this does not apply to the |
| 57 | // initialization with PyConfig. |
| 58 | PyConfig_InitPythonConfig(&py_config); |
| 59 | BOOST_SCOPE_EXIT_ALL(&py_config) { |
| 60 | PyConfig_Clear(&py_config); |
| 61 | }; |
| 62 | #if PY_VERSION_HEX >= 0x030b0000 |
| 63 | py_config.safe_path = 0; |
| 64 | #endif |
| 65 | py_config.parse_argv = 0; |
| 66 | py_config.configure_c_stdio = 0; |
| 67 | py_config.install_signal_handlers = 0; |
| 68 | py_config.pathconfig_warnings = 0; |
| 69 | |
| 70 | PyStatus status; |
| 71 | status = PyConfig_SetString(&py_config, &py_config.program_name, WCHAR(MGR_PYTHON_EXECUTABLE)); |
| 72 | ceph_assertf(!PyStatus_Exception(status), "PyConfig_SetString: %s:%s", status.func, status.err_msg); |
| 73 | // Some python modules do not cope with an unpopulated argv, so lets |
| 74 | // fake one. This step also picks up site-packages into sys.path. |
| 75 | const wchar_t* argv[] = {L"ceph-mgr"}; |
| 76 | status = PyConfig_SetArgv(&py_config, 1, (wchar_t *const *)argv); |
| 77 | ceph_assertf(!PyStatus_Exception(status), "PyConfig_SetArgv: %s:%s", status.func, status.err_msg); |
| 78 | // Add more modules |
| 79 | if (g_conf().get_val<bool>("daemonize")) { |
| 80 | PyImport_AppendInittab("ceph_logger", PyModule::init_ceph_logger); |
| 81 | } |
| 82 | PyImport_AppendInittab("ceph_module", PyModule::init_ceph_module); |
| 83 | // Configure sys.path to include mgr_module_path |
| 84 | auto pythonpath_env = g_conf().get_val<std::string>("mgr_module_path"); |
| 85 | if (const char* pythonpath = getenv("PYTHONPATH")) { |
| 86 | pythonpath_env += ":"; |
| 87 | pythonpath_env += pythonpath; |
| 88 | } |
| 89 | status = PyConfig_SetBytesString(&py_config, &py_config.pythonpath_env, pythonpath_env.data()); |
| 90 | ceph_assertf(!PyStatus_Exception(status), "PyConfig_SetBytesString: %s:%s", status.func, status.err_msg); |
| 91 | dout(10) << "set PYTHONPATH to " << std::quoted(pythonpath_env) << dendl; |
| 92 | status = Py_InitializeFromConfig(&py_config); |
| 93 | ceph_assertf(!PyStatus_Exception(status), "Py_InitializeFromConfig: %s:%s", status.func, status.err_msg); |
| 94 | #undef WCHAR |
| 95 | |
| 96 | // Drop the GIL and remember the main thread state (current |
| 97 | // thread state becomes NULL) |
| 98 | pMainThreadState = PyEval_SaveThread(); |
| 99 | ceph_assert(pMainThreadState != nullptr); |
| 100 | |
| 101 | std::list<std::string> failed_modules; |
| 102 | thread_monitor->start_monitoring(); |
nothing calls this directly
no test coverage detected