diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -395,6 +395,81 @@ #define DEFAULT_DIR_FD (-100) #endif +typedef struct { + int initialized; + long ticks_per_second; + newfunc structseq_new; + PyObject *UnameResultType; + PyObject *TimesResultType; + PyObject *TerminalSizeType; +#if defined(HAVE_WAITID) && !defined(__APPLE__) + PyObject *WaitidResultType; +#endif + PyObject *StatResultType; + PyObject *StatVFSResultType; +#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) + PyObject *SchedParamType; +#endif + PyObject *billion; + PyObject *struct_rusage; + PyObject *posix_putenv_garbage; +} posixstate; + +#define posix_state(o) ((posixstate *)PyModule_GetState(o)) + +static int +posix_clear(PyObject *m) +{ + posixstate *state = posix_state(m); + Py_CLEAR(state->UnameResultType); + Py_CLEAR(state->TimesResultType); + Py_CLEAR(state->TerminalSizeType); +#if defined(HAVE_WAITID) && !defined(__APPLE__) + Py_CLEAR(state->WaitidResultType); +#endif + Py_CLEAR(state->StatResultType); + Py_CLEAR(state->StatVFSResultType); +#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) + Py_CLEAR(state->SchedParamType); +#endif + Py_CLEAR(state->billion); + Py_CLEAR(state->struct_rusage); + Py_CLEAR(state->posix_putenv_garbage); + return 0; +} + +static int +posix_traverse(PyObject *m, visitproc visit, void *arg) +{ + posixstate *state = posix_state(m); + Py_VISIT(state->UnameResultType); + Py_VISIT(state->TimesResultType); + Py_VISIT(state->TerminalSizeType); +#if defined(HAVE_WAITID) && !defined(__APPLE__) + Py_VISIT(state->WaitidResultType); +#endif + Py_VISIT(state->StatResultType); + Py_VISIT(state->StatVFSResultType); +#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) + Py_VISIT(state->SchedParamType); +#endif + Py_VISIT(state->billion); + Py_VISIT(state->struct_rusage); + Py_VISIT(state->posix_putenv_garbage); + return 0; +} + +static void +posix_free(void *m) +{ + posix_clear((PyObject *)m); +} + +static PyModuleDef posixmodule; + +#define posixstate_global ((posixstate *)PyModule_GetState(PyState_FindModule(&posixmodule))) + + static int _fd_converter(PyObject *o, int *p, int default_value) { long long_value; @@ -1823,16 +1898,12 @@ waitid_result_fields, 5 }; -static PyTypeObject WaitidResultType; -#endif - -static int initialized; -static PyTypeObject StatResultType; -static PyTypeObject StatVFSResultType; + +#endif + #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) -static PyTypeObject SchedParamType; -#endif -static newfunc structseq_new; + +#endif static PyObject * statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds) @@ -1840,7 +1911,7 @@ PyStructSequence *result; int i; - result = (PyStructSequence*)structseq_new(type, args, kwds); + result = (PyStructSequence*)posixstate_global->structseq_new(type, args, kwds); if (!result) return NULL; /* If we have been initialized from a tuple, @@ -1886,7 +1957,7 @@ return Py_None; } -static PyObject *billion = NULL; + static void fill_time(PyObject *v, int index, time_t sec, unsigned long nsec) @@ -1900,7 +1971,7 @@ if (!(s && ns_fractional)) goto exit; - s_in_ns = PyNumber_Multiply(s, billion); + s_in_ns = PyNumber_Multiply(s, posixstate_global->billion); if (!s_in_ns) goto exit; @@ -1938,7 +2009,7 @@ _pystat_fromstructstat(STRUCT_STAT *st) { unsigned long ansec, mnsec, cnsec; - PyObject *v = PyStructSequence_New(&StatResultType); + PyObject *v = PyStructSequence_New((PyTypeObject *)posixstate_global->StatResultType); if (v == NULL) return NULL; @@ -4088,9 +4159,6 @@ 5 }; -static PyTypeObject UnameResultType; - - #ifdef HAVE_UNAME static PyObject * posix_uname(PyObject *self, PyObject *noargs) @@ -4105,7 +4173,7 @@ if (res < 0) return posix_error(); - value = PyStructSequence_New(&UnameResultType); + value = PyStructSequence_New((PyTypeObject *)posixstate_global->UnameResultType); if (value == NULL) return NULL; @@ -4309,7 +4377,7 @@ { int result = 0; PyObject *divmod; - divmod = PyNumber_Divmod(py_long, billion); + divmod = PyNumber_Divmod(py_long, posixstate_global->billion); if (!divmod) goto exit; *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0)); @@ -5139,7 +5207,7 @@ { long priority; - if (Py_TYPE(param) != &SchedParamType) { + if (Py_TYPE(param) != posixstate_global->SchedParamType) { PyErr_SetString(PyExc_TypeError, "must have a sched_param object"); return 0; } @@ -5205,7 +5273,7 @@ return NULL; if (sched_getparam(pid, ¶m)) return posix_error(); - res = PyStructSequence_New(&SchedParamType); + res = PyStructSequence_New((PyTypeObject *)posixstate_global->SchedParamType); if (!res) return NULL; priority = PyLong_FromLong(param.sched_priority); @@ -6297,24 +6365,24 @@ wait_helper(pid_t pid, int status, struct rusage *ru) { PyObject *result; - static PyObject *struct_rusage; + PyObject *struct_rusage = posixstate_global->struct_rusage; _Py_IDENTIFIER(struct_rusage); if (pid == -1) return posix_error(); - if (struct_rusage == NULL) { + if (posixstate_global->struct_rusage == NULL) { PyObject *m = PyImport_ImportModuleNoBlock("resource"); if (m == NULL) return NULL; - struct_rusage = _PyObject_GetAttrId(m, &PyId_struct_rusage); + posixstate_global->struct_rusage = _PyObject_GetAttrId(m, &PyId_struct_rusage); Py_DECREF(m); - if (struct_rusage == NULL) + if (posixstate_global->struct_rusage == NULL) return NULL; } /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */ - result = PyStructSequence_New((PyTypeObject*) struct_rusage); + result = PyStructSequence_New((PyTypeObject *)posixstate_global->struct_rusage); if (!result) return NULL; @@ -6434,7 +6502,7 @@ if (si.si_pid == 0) Py_RETURN_NONE; - result = PyStructSequence_New(&WaitidResultType); + result = PyStructSequence_New((PyTypeObject *)posixstate_global->WaitidResultType); if (!result) return NULL; @@ -6823,7 +6891,6 @@ 5 }; -static PyTypeObject TimesResultType; #ifdef MS_WINDOWS #define HAVE_TIMES /* mandatory, for the method table */ @@ -6836,7 +6903,7 @@ double children_user, double children_system, double elapsed) { - PyObject *value = PyStructSequence_New(&TimesResultType); + PyObject *value = PyStructSequence_New((PyTypeObject *)posixstate_global->TimesResultType); if (value == NULL) return NULL; @@ -6891,7 +6958,6 @@ } #else /* Not Windows */ #define NEED_TICKS_PER_SECOND -static long ticks_per_second = -1; static PyObject * posix_times(PyObject *self, PyObject *noargs) { @@ -6902,11 +6968,11 @@ if (c == (clock_t) -1) return posix_error(); return build_times_result( - (double)t.tms_utime / ticks_per_second, - (double)t.tms_stime / ticks_per_second, - (double)t.tms_cutime / ticks_per_second, - (double)t.tms_cstime / ticks_per_second, - (double)c / ticks_per_second); + (double)t.tms_utime / posixstate_global->ticks_per_second, + (double)t.tms_stime / posixstate_global->ticks_per_second, + (double)t.tms_cutime / posixstate_global->ticks_per_second, + (double)t.tms_cstime / posixstate_global->ticks_per_second, + (double)c / posixstate_global->ticks_per_second); } #endif @@ -8038,7 +8104,7 @@ /* Save putenv() parameters as values here, so we can collect them when they * get re-set with another call for the same key. */ -static PyObject *posix_putenv_garbage; + static PyObject * posix_putenv(PyObject *self, PyObject *args) @@ -8102,7 +8168,7 @@ * this will cause previous value to be collected. This has to * happen after the real putenv() call because the old value * was still accessible until then. */ - if (PyDict_SetItem(posix_putenv_garbage, os1, newstr)) { + if (PyDict_SetItem(posixstate_global->posix_putenv_garbage, os1, newstr)) { /* really not much we can do; just leak */ PyErr_Clear(); } @@ -8159,7 +8225,7 @@ * happen after the real unsetenv() call because the * old value was still accessible until then. */ - if (PyDict_DelItem(posix_putenv_garbage, name)) { + if (PyDict_DelItem(posixstate_global->posix_putenv_garbage, name)) { /* really not much we can do; just leak */ PyErr_Clear(); } @@ -8352,7 +8418,7 @@ static PyObject* _pystatvfs_fromstructstatvfs(struct statvfs st) { - PyObject *v = PyStructSequence_New(&StatVFSResultType); + PyObject *v = PyStructSequence_New((PyTypeObject *)posixstate_global->StatVFSResultType); if (v == NULL) return NULL; @@ -10094,7 +10160,6 @@ /* Terminal size querying */ -static PyTypeObject TerminalSizeType; PyDoc_STRVAR(TerminalSize_docstring, "A tuple of (columns, lines) for holding terminal window size"); @@ -10185,7 +10250,7 @@ } #endif /* TERMSIZE_USE_CONIO */ - termsize = PyStructSequence_New(&TerminalSizeType); + termsize = PyStructSequence_New((PyTypeObject *)posixstate_global->TerminalSizeType); if (termsize == NULL) return NULL; PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns)); @@ -11070,12 +11135,12 @@ PyModuleDef_HEAD_INIT, MODNAME, posix__doc__, - -1, + sizeof(posixstate), posix_methods, NULL, - NULL, - NULL, - NULL + posix_traverse, + posix_clear, + posix_free }; @@ -11211,14 +11276,20 @@ PyObject *m, *v; PyObject *list; char **trace; + posixstate *state; #if defined(HAVE_SYMLINK) && defined(MS_WINDOWS) win32_can_symlink = enable_symlink(); #endif - - m = PyModule_Create(&posixmodule); - if (m == NULL) - return NULL; + m = PyState_FindModule(&posixmodule); + if(m == NULL) { + m = PyModule_Create(&posixmodule); + if (m == NULL) + return NULL; + posix_state(m)->initialized = 0; + } + + state = posix_state(m); /* Initialize environ dictionary */ v = convertenviron(); @@ -11237,67 +11308,77 @@ PyModule_AddObject(m, "error", PyExc_OSError); #ifdef HAVE_PUTENV - if (posix_putenv_garbage == NULL) - posix_putenv_garbage = PyDict_New(); -#endif - - if (!initialized) { + if (state->posix_putenv_garbage == NULL) + state->posix_putenv_garbage = PyDict_New(); +#endif + + if (!state->initialized) { #if defined(HAVE_WAITID) && !defined(__APPLE__) waitid_result_desc.name = MODNAME ".waitid_result"; - PyStructSequence_InitType(&WaitidResultType, &waitid_result_desc); + state->WaitidResultType = + (PyObject *)PyStructSequence_NewType(&waitid_result_desc); #endif stat_result_desc.name = MODNAME ".stat_result"; stat_result_desc.fields[7].name = PyStructSequence_UnnamedField; stat_result_desc.fields[8].name = PyStructSequence_UnnamedField; stat_result_desc.fields[9].name = PyStructSequence_UnnamedField; - PyStructSequence_InitType(&StatResultType, &stat_result_desc); - structseq_new = StatResultType.tp_new; - StatResultType.tp_new = statresult_new; + state->StatResultType = + (PyObject *)PyStructSequence_NewType(&stat_result_desc); + state->structseq_new = ((PyTypeObject *)state->StatResultType)->tp_new; + ((PyTypeObject *)state->StatResultType)->tp_new = statresult_new; statvfs_result_desc.name = MODNAME ".statvfs_result"; - PyStructSequence_InitType(&StatVFSResultType, &statvfs_result_desc); + state->StatVFSResultType = + (PyObject *)PyStructSequence_NewType(&statvfs_result_desc); + #ifdef NEED_TICKS_PER_SECOND # if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK) - ticks_per_second = sysconf(_SC_CLK_TCK); + state->ticks_per_second = sysconf(_SC_CLK_TCK); # elif defined(HZ) - ticks_per_second = HZ; + state->ticks_per_second = HZ; # else - ticks_per_second = 60; /* magic fallback value; may be bogus */ + state->ticks_per_second = 60; /* magic fallback value; may be bogus */ # endif #endif #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) sched_param_desc.name = MODNAME ".sched_param"; - PyStructSequence_InitType(&SchedParamType, &sched_param_desc); - SchedParamType.tp_new = sched_param_new; + state->SchedParamType = + (PyObject *)PyStructSequence_NewType(&sched_param_desc); + ((PyTypeObject *)state->SchedParamType)->tp_new = sched_param_new; #endif /* initialize TerminalSize_info */ - PyStructSequence_InitType(&TerminalSizeType, &TerminalSize_desc); + state->TerminalSizeType = + (PyObject *)PyStructSequence_NewType(&TerminalSize_desc); + Py_INCREF(state->TerminalSizeType); } #if defined(HAVE_WAITID) && !defined(__APPLE__) - Py_INCREF((PyObject*) &WaitidResultType); - PyModule_AddObject(m, "waitid_result", (PyObject*) &WaitidResultType); -#endif - Py_INCREF((PyObject*) &StatResultType); - PyModule_AddObject(m, "stat_result", (PyObject*) &StatResultType); - Py_INCREF((PyObject*) &StatVFSResultType); + Py_INCREF(state->WaitidResultType); + PyModule_AddObject(m, "waitid_result", state->WaitidResultType); +#endif + Py_INCREF(state->StatResultType); + PyModule_AddObject(m, "stat_result", state->StatResultType); + Py_INCREF(state->StatVFSResultType); PyModule_AddObject(m, "statvfs_result", - (PyObject*) &StatVFSResultType); + state->StatVFSResultType); #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) - Py_INCREF(&SchedParamType); - PyModule_AddObject(m, "sched_param", (PyObject *)&SchedParamType); + Py_INCREF(state->SchedParamType); + PyModule_AddObject(m, "sched_param", state->SchedParamType); + #endif times_result_desc.name = MODNAME ".times_result"; - PyStructSequence_InitType(&TimesResultType, ×_result_desc); - PyModule_AddObject(m, "times_result", (PyObject *)&TimesResultType); + state->TimesResultType = + (PyObject *)PyStructSequence_NewType(×_result_desc); + PyModule_AddObject(m, "times_result", state->TimesResultType); uname_result_desc.name = MODNAME ".uname_result"; - PyStructSequence_InitType(&UnameResultType, &uname_result_desc); - PyModule_AddObject(m, "uname_result", (PyObject *)&UnameResultType); + state->UnameResultType = + (PyObject *)PyStructSequence_NewType(&uname_result_desc); + PyModule_AddObject(m, "uname_result", state->UnameResultType); #ifdef __APPLE__ /* @@ -11337,11 +11418,11 @@ #endif /* __APPLE__ */ - Py_INCREF(&TerminalSizeType); - PyModule_AddObject(m, "terminal_size", (PyObject*) &TerminalSizeType); - - billion = PyLong_FromLong(1000000000); - if (!billion) + Py_INCREF(state->TerminalSizeType); + PyModule_AddObject(m, "terminal_size", state->TerminalSizeType); + + state->billion = PyLong_FromLong(1000000000); + if (!state->billion) return NULL; /* suppress "function not used" warnings */ @@ -11371,12 +11452,12 @@ } PyModule_AddObject(m, "_have_functions", list); - initialized = 1; - + state->initialized = 1; + Py_INCREF(m); return m; - } #ifdef __cplusplus } #endif +