Skip to content

Commit 3f05d65

Browse files
committed
Use PyConfig API on Python 3.8
The following functions used by mod_wsgi are deprecated: * PySys_AddWarnOption() * Py_SetProgramName() * Py_SetPythonHome() Replace deprecated functions with the PyConfig API on Python 3.8. On error (usually memory allocation failure), log a critical message. Replace: * Py_OptimizeFlag: config.optimization_level * PYTHONHASHSEED: config.use_hash_seed and config.hash_seed * PySys_AddWarnOption(): PyWideStringList_Append(&config.warnoptions) * Py_SetPythonHome(): PyConfig_SetString(&config.home) * Py_SetProgramName(): PyConfig_SetString(&config.program_name) * Py_Initialize(): Py_InitializeFromConfig() The PYTHONHASHSEED environment variable is no longer set and so doesn't need to be unset later.
1 parent f54eadd commit 3f05d65

File tree

1 file changed

+90
-18
lines changed

1 file changed

+90
-18
lines changed

src/server/wsgi_interp.c

+90-18
Original file line numberDiff line numberDiff line change
@@ -2165,12 +2165,33 @@ static apr_status_t wsgi_python_parent_cleanup(void *data)
21652165
}
21662166

21672167

2168+
static void wsgi_python_init_failed(PyStatus status)
2169+
{
2170+
/*
2171+
* On a PyConfig API failure, usually a memory allocation failure,
2172+
* log a critical error.
2173+
*/
2174+
ap_log_error(APLOG_MARK, APLOG_CRIT, 0, wsgi_server,
2175+
"mod_wsgi (pid=%d): Initializing Python failed: %s",
2176+
getpid(), status.err_msg);
2177+
}
2178+
2179+
21682180
void wsgi_python_init(apr_pool_t *p)
21692181
{
21702182
const char *python_home = 0;
21712183

21722184
int is_pyvenv = 0;
21732185

2186+
#if PY_VERSION_HEX >= 0x03080000
2187+
# define USE_PYCONFIG
2188+
#endif
2189+
#ifdef USE_PYCONFIG
2190+
PyConfig config;
2191+
PyStatus status;
2192+
PyConfig_InitPythonConfig(&config);
2193+
#endif
2194+
21742195
/* Perform initialisation if required. */
21752196

21762197
if (!Py_IsInitialized()) {
@@ -2186,16 +2207,30 @@ void wsgi_python_init(apr_pool_t *p)
21862207

21872208
#if (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 3) || \
21882209
(PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION >= 6)
2189-
if (wsgi_server_config->dont_write_bytecode == 1)
2210+
if (wsgi_server_config->dont_write_bytecode == 1) {
2211+
#ifdef USE_PYCONFIG
2212+
config.write_bytecode = 0;
2213+
#else
21902214
Py_DontWriteBytecodeFlag++;
21912215
#endif
2216+
}
2217+
#endif
21922218

21932219
/* Check for Python paths and optimisation flag. */
21942220

2195-
if (wsgi_server_config->python_optimize > 0)
2221+
if (wsgi_server_config->python_optimize > 0) {
2222+
#ifdef USE_PYCONFIG
2223+
config.optimization_level = wsgi_server_config->python_optimize;
2224+
#else
21962225
Py_OptimizeFlag = wsgi_server_config->python_optimize;
2197-
else
2226+
#endif
2227+
} else {
2228+
#ifdef USE_PYCONFIG
2229+
config.optimization_level = 0;
2230+
#else
21982231
Py_OptimizeFlag = 0;
2232+
#endif
2233+
}
21992234

22002235
/* Check for control options for Python warnings. */
22012236

@@ -2215,12 +2250,18 @@ void wsgi_python_init(apr_pool_t *p)
22152250

22162251
s = (wchar_t *)apr_palloc(p, len*sizeof(wchar_t));
22172252

2218-
#if defined(WIN32) && defined(APR_HAS_UNICODE_FS)
2253+
# if defined(WIN32) && defined(APR_HAS_UNICODE_FS)
22192254
wsgi_utf8_to_unicode_path(s, len, entries[i]);
2220-
#else
2255+
# else
22212256
mbstowcs(s, entries[i], len);
2222-
#endif
2257+
# endif
2258+
# ifdef USE_PYCONFIG
2259+
status = PyWideStringList_Append(&config.warnoptions, s);
2260+
if (PyStatus_Exception(status))
2261+
wsgi_python_init_failed(status);
2262+
# else
22232263
PySys_AddWarnOption(s);
2264+
# endif
22242265
#else
22252266
PySys_AddWarnOption(entries[i]);
22262267
#endif
@@ -2265,12 +2306,17 @@ void wsgi_python_init(apr_pool_t *p)
22652306

22662307
s = (wchar_t *)apr_palloc(p, len*sizeof(wchar_t));
22672308

2268-
#if defined(WIN32) && defined(APR_HAS_UNICODE_FS)
2309+
# if defined(WIN32) && defined(APR_HAS_UNICODE_FS)
22692310
wsgi_utf8_to_unicode_path(s, len, python_home);
2270-
#else
2311+
# else
22712312
mbstowcs(s, python_home, len);
2272-
#endif
2313+
# endif
2314+
# ifdef USE_PYCONFIG
2315+
status = PyConfig_SetString(&config, &config.home, s);
2316+
if (PyStatus_Exception(status)) wsgi_python_init_failed(status);
2317+
# else
22732318
Py_SetPythonHome(s);
2319+
# endif
22742320
#else
22752321
Py_SetPythonHome((char *)python_home);
22762322
#endif
@@ -2375,13 +2421,19 @@ void wsgi_python_init(apr_pool_t *p)
23752421
#if PY_MAJOR_VERSION >= 3
23762422
len = strlen(python_exe)+1;
23772423
s = (wchar_t *)apr_palloc(p, len*sizeof(wchar_t));
2378-
#if defined(WIN32) && defined(APR_HAS_UNICODE_FS)
2424+
# if defined(WIN32) && defined(APR_HAS_UNICODE_FS)
23792425
wsgi_utf8_to_unicode_path(s, len, python_exe);
2380-
#else
2426+
# else
23812427
mbstowcs(s, python_exe, len);
2382-
#endif
2428+
# endif
23832429

2430+
# ifdef USE_PYCONFIG
2431+
status = PyConfig_SetString(&config, &config.program_name, s);
2432+
if (PyStatus_Exception(status))
2433+
wsgi_python_init_failed(status);
2434+
# else
23842435
Py_SetProgramName(s);
2436+
# endif
23852437
#else
23862438
Py_SetProgramName((char *)python_exe);
23872439
#endif
@@ -2390,13 +2442,19 @@ void wsgi_python_init(apr_pool_t *p)
23902442
#if PY_MAJOR_VERSION >= 3
23912443
len = strlen(python_home)+1;
23922444
s = (wchar_t *)apr_palloc(p, len*sizeof(wchar_t));
2393-
#if defined(WIN32) && defined(APR_HAS_UNICODE_FS)
2445+
# if defined(WIN32) && defined(APR_HAS_UNICODE_FS)
23942446
wsgi_utf8_to_unicode_path(s, len, python_home);
2395-
#else
2447+
# else
23962448
mbstowcs(s, python_home, len);
2397-
#endif
2449+
# endif
23982450

2451+
# ifdef USE_PYCONFIG
2452+
status = PyConfig_SetString(&config, &config.home, s);
2453+
if (PyStatus_Exception(status))
2454+
wsgi_python_init_failed(status);
2455+
# else
23992456
Py_SetPythonHome(s);
2457+
# endif
24002458
#else
24012459
Py_SetPythonHome((char *)python_home);
24022460
#endif
@@ -2412,12 +2470,18 @@ void wsgi_python_init(apr_pool_t *p)
24122470
*/
24132471

24142472
if (wsgi_server_config->python_hash_seed != NULL) {
2415-
char *envvar = apr_pstrcat(p, "PYTHONHASHSEED=",
2416-
wsgi_server_config->python_hash_seed, NULL);
24172473
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, wsgi_server,
24182474
"mod_wsgi (pid=%d): Setting hash seed to %s.",
24192475
getpid(), wsgi_server_config->python_hash_seed);
2476+
#ifdef USE_PYCONFIG
2477+
long seed = atol(wsgi_server_config->python_hash_seed);
2478+
config.use_hash_seed = 1;
2479+
config.hash_seed = (unsigned long)seed;
2480+
#else
2481+
char *envvar = apr_pstrcat(p, "PYTHONHASHSEED=",
2482+
wsgi_server_config->python_hash_seed, NULL);
24202483
putenv(envvar);
2484+
#endif
24212485
}
24222486

24232487
/*
@@ -2436,12 +2500,19 @@ void wsgi_python_init(apr_pool_t *p)
24362500
ap_log_error(APLOG_MARK, APLOG_INFO, 0, wsgi_server,
24372501
"mod_wsgi (pid=%d): Initializing Python.", getpid());
24382502

2503+
#ifdef USE_PYCONFIG
2504+
status = Py_InitializeFromConfig(&config);
2505+
if (PyStatus_Exception(status)) wsgi_python_init_failed(status);
2506+
#else
24392507
Py_Initialize();
2508+
#endif
24402509

24412510
#if PY_VERSION_HEX < 0x03090000
24422511
/* Initialise threading. */
24432512
PyEval_InitThreads();
24442513
#endif
2514+
2515+
#ifndef USE_PYCONFIG
24452516
/*
24462517
* Remove the environment variable we set for the hash
24472518
* seed. This has to be done in os.environ, which will
@@ -2478,7 +2549,8 @@ void wsgi_python_init(apr_pool_t *p)
24782549
Py_DECREF(module);
24792550
}
24802551
}
2481-
2552+
#endif
2553+
24822554
/*
24832555
* We now want to release the GIL. Before we do that
24842556
* though we remember what the current thread state is.

0 commit comments

Comments
 (0)