bpo-39406: Add PY_PUTENV_DICT macro to posixmodule.c (GH-18106)

Rename posix_putenv_garbage to putenv_dict.
This commit is contained in:
Victor Stinner 2020-01-21 19:25:32 +01:00 committed by GitHub
parent 56cd3710a1
commit 623ed6171e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 37 additions and 15 deletions

View File

@ -819,9 +819,19 @@ dir_fd_converter(PyObject *o, void *p)
} }
} }
#ifdef HAVE_PUTENV
# define PY_PUTENV_DICT
#endif
typedef struct { typedef struct {
PyObject *billion; PyObject *billion;
PyObject *posix_putenv_garbage; #ifdef PY_PUTENV_DICT
/* putenv() and _wputenv() requires that the caller manages the environment
variable memory. Use a Python dictionary for that: name => env, where
env is a string like "name=value". On Windows, dict keys and values are
Unicode strings. On Unix, they are bytes strings. */
PyObject *putenv_dict;
#endif
PyObject *DirEntryType; PyObject *DirEntryType;
PyObject *ScandirIteratorType; PyObject *ScandirIteratorType;
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
@ -2105,7 +2115,9 @@ static int
_posix_clear(PyObject *module) _posix_clear(PyObject *module)
{ {
Py_CLEAR(_posixstate(module)->billion); Py_CLEAR(_posixstate(module)->billion);
Py_CLEAR(_posixstate(module)->posix_putenv_garbage); #ifdef PY_PUTENV_DICT
Py_CLEAR(_posixstate(module)->putenv_dict);
#endif
Py_CLEAR(_posixstate(module)->DirEntryType); Py_CLEAR(_posixstate(module)->DirEntryType);
Py_CLEAR(_posixstate(module)->ScandirIteratorType); Py_CLEAR(_posixstate(module)->ScandirIteratorType);
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
@ -2130,7 +2142,9 @@ static int
_posix_traverse(PyObject *module, visitproc visit, void *arg) _posix_traverse(PyObject *module, visitproc visit, void *arg)
{ {
Py_VISIT(_posixstate(module)->billion); Py_VISIT(_posixstate(module)->billion);
Py_VISIT(_posixstate(module)->posix_putenv_garbage); #ifdef PY_PUTENV_DICT
Py_VISIT(_posixstate(module)->putenv_dict);
#endif
Py_VISIT(_posixstate(module)->DirEntryType); Py_VISIT(_posixstate(module)->DirEntryType);
Py_VISIT(_posixstate(module)->ScandirIteratorType); Py_VISIT(_posixstate(module)->ScandirIteratorType);
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM) #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
@ -10047,23 +10061,26 @@ os_posix_fadvise_impl(PyObject *module, int fd, Py_off_t offset,
} }
#endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */ #endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */
#ifdef HAVE_PUTENV
#ifdef PY_PUTENV_DICT
static void static void
posix_putenv_garbage_setitem(PyObject *name, PyObject *value) posix_putenv_dict_setitem(PyObject *name, PyObject *value)
{ {
/* Install the first arg and newstr in posix_putenv_garbage; /* Install the first arg and newstr in putenv_dict;
* this will cause previous value to be collected. This has to * this will cause previous value to be collected. This has to
* happen after the real putenv() call because the old value * happen after the real putenv() call because the old value
* was still accessible until then. */ * was still accessible until then. */
if (PyDict_SetItem(_posixstate_global->posix_putenv_garbage, name, value)) if (PyDict_SetItem(_posixstate_global->putenv_dict, name, value))
/* really not much we can do; just leak */ /* really not much we can do; just leak */
PyErr_Clear(); PyErr_Clear();
else else
Py_DECREF(value); Py_DECREF(value);
} }
#endif /* PY_PUTENV_DICT */
#ifdef HAVE_PUTENV
#ifdef MS_WINDOWS #ifdef MS_WINDOWS
/*[clinic input] /*[clinic input]
os.putenv os.putenv
@ -10114,7 +10131,7 @@ os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
goto error; goto error;
} }
posix_putenv_garbage_setitem(name, unicode); posix_putenv_dict_setitem(name, unicode);
Py_RETURN_NONE; Py_RETURN_NONE;
error: error:
@ -10156,7 +10173,7 @@ os_putenv_impl(PyObject *module, PyObject *name, PyObject *value)
return posix_error(); return posix_error();
} }
posix_putenv_garbage_setitem(name, bytes); posix_putenv_dict_setitem(name, bytes);
Py_RETURN_NONE; Py_RETURN_NONE;
} }
#endif /* MS_WINDOWS */ #endif /* MS_WINDOWS */
@ -10189,18 +10206,20 @@ os_unsetenv_impl(PyObject *module, PyObject *name)
return PyErr_SetFromWindowsErr(0); return PyErr_SetFromWindowsErr(0);
} }
/* Remove the key from posix_putenv_garbage; #ifdef PY_PUTENV_DICT
/* Remove the key from putenv_dict;
* this will cause it to be collected. This has to * this will cause it to be collected. This has to
* happen after the real unsetenv() call because the * happen after the real unsetenv() call because the
* old value was still accessible until then. * old value was still accessible until then.
*/ */
if (PyDict_DelItem(_posixstate(module)->posix_putenv_garbage, name)) { if (PyDict_DelItem(_posixstate(module)->putenv_dict, name)) {
/* really not much we can do; just leak */ /* really not much we can do; just leak */
if (!PyErr_ExceptionMatches(PyExc_KeyError)) { if (!PyErr_ExceptionMatches(PyExc_KeyError)) {
return NULL; return NULL;
} }
PyErr_Clear(); PyErr_Clear();
} }
#endif
Py_RETURN_NONE; Py_RETURN_NONE;
} }
@ -10230,18 +10249,21 @@ os_unsetenv_impl(PyObject *module, PyObject *name)
return posix_error(); return posix_error();
#endif #endif
/* Remove the key from posix_putenv_garbage; #ifdef PY_PUTENV_DICT
/* Remove the key from putenv_dict;
* this will cause it to be collected. This has to * this will cause it to be collected. This has to
* happen after the real unsetenv() call because the * happen after the real unsetenv() call because the
* old value was still accessible until then. * old value was still accessible until then.
*/ */
if (PyDict_DelItem(_posixstate(module)->posix_putenv_garbage, name)) { if (PyDict_DelItem(_posixstate(module)->putenv_dict, name)) {
/* really not much we can do; just leak */ /* really not much we can do; just leak */
if (!PyErr_ExceptionMatches(PyExc_KeyError)) { if (!PyErr_ExceptionMatches(PyExc_KeyError)) {
return NULL; return NULL;
} }
PyErr_Clear(); PyErr_Clear();
} }
#endif
Py_RETURN_NONE; Py_RETURN_NONE;
} }
#endif /* HAVE_UNSETENV */ #endif /* HAVE_UNSETENV */
@ -14538,10 +14560,10 @@ INITFUNC(void)
Py_INCREF(PyExc_OSError); Py_INCREF(PyExc_OSError);
PyModule_AddObject(m, "error", PyExc_OSError); PyModule_AddObject(m, "error", PyExc_OSError);
#ifdef HAVE_PUTENV #ifdef PY_PUTENV_DICT
/* Save putenv() parameters as values here, so we can collect them when they /* Save putenv() parameters as values here, so we can collect them when they
* get re-set with another call for the same key. */ * get re-set with another call for the same key. */
_posixstate(m)->posix_putenv_garbage = PyDict_New(); _posixstate(m)->putenv_dict = PyDict_New();
#endif #endif
#if defined(HAVE_WAITID) && !defined(__APPLE__) #if defined(HAVE_WAITID) && !defined(__APPLE__)