diff -r 97cdad5e026f Modules/socketmodule.c --- a/Modules/socketmodule.c Thu Aug 16 23:17:00 2012 +0200 +++ b/Modules/socketmodule.c Thu Aug 16 23:23:43 2012 +0200 @@ -454,7 +454,6 @@ #if !defined(NI_MAXSERV) #define NI_MAXSERV 32 #endif - #ifndef INVALID_SOCKET /* MS defines this */ #define INVALID_SOCKET (-1) #endif @@ -464,15 +463,55 @@ /* Global variable holding the exception type for errors detected by this module (but not argument type or memory errors, etc.). */ -static PyObject *socket_herror; -static PyObject *socket_gaierror; -static PyObject *socket_timeout; +typedef struct { + PyObject *socket_herror; + PyObject *socket_gaierror; + PyObject *socket_timeout; + PyObject *sock_type; +} socketstate; + + +#define socket_state(o) ((socketstate *)PyModule_GetState(o)) + +static int +socket_clear(PyObject *m) +{ + socketstate *state = socket_state(m); + Py_CLEAR(state->socket_herror); + Py_CLEAR(state->socket_gaierror); + Py_CLEAR(state->socket_timeout); + Py_CLEAR(state->sock_type); + return 0; +} + +static int +socket_traverse(PyObject *m, visitproc visit, void *arg) +{ + socketstate *state = socket_state(m); + Py_VISIT(state->socket_herror); + Py_VISIT(state->socket_gaierror); + Py_VISIT(state->socket_timeout); + Py_VISIT(state->sock_type); + return 0; +} + +static void +socket_free(void *m) +{ + socket_clear((PyObject *)m); +} + +static PyModuleDef socketmodule; + +#define socketstate_global ((socketstate *)PyModule_GetState(PyState_FindModule(&socketmodule))) + + + /* A forward reference to the socket type object. The sock_type variable contains pointers to various functions, some of which call new_sockobject(), which uses sock_type, so there has to be a circular reference. */ -static PyTypeObject sock_type; #if defined(HAVE_POLL_H) #include @@ -585,7 +624,7 @@ v = Py_BuildValue("(is)", h_error, "host not found"); #endif if (v != NULL) { - PyErr_SetObject(socket_herror, v); + PyErr_SetObject(socketstate_global->socket_herror, v); Py_DECREF(v); } @@ -610,7 +649,7 @@ v = Py_BuildValue("(is)", error, "getaddrinfo failed"); #endif if (v != NULL) { - PyErr_SetObject(socket_gaierror, v); + PyErr_SetObject(socketstate_global->socket_gaierror, v); Py_DECREF(v); } @@ -830,7 +869,7 @@ { PySocketSockObject *s; s = (PySocketSockObject *) - PyType_GenericNew(&sock_type, NULL, NULL); + PyType_GenericNew((PyTypeObject *)socketstate_global->sock_type, NULL, NULL); if (s != NULL) init_sockobject(s, fd, family, type, proto); return s; @@ -2030,7 +2069,7 @@ Py_END_ALLOW_THREADS if (timeout == 1) { - PyErr_SetString(socket_timeout, "timed out"); + PyErr_SetString(socketstate_global->socket_timeout, "timed out"); return NULL; } END_SELECT_LOOP(s) @@ -2423,7 +2462,7 @@ Py_END_ALLOW_THREADS if (timeout == 1) { - PyErr_SetString(socket_timeout, "timed out"); + PyErr_SetString(socketstate_global->socket_timeout, "timed out"); return NULL; } if (res != 0) @@ -2616,7 +2655,7 @@ Py_END_ALLOW_THREADS if (timeout == 1) { - PyErr_SetString(socket_timeout, "timed out"); + PyErr_SetString(socketstate_global->socket_timeout, "timed out"); return -1; } END_SELECT_LOOP(s) @@ -2648,7 +2687,7 @@ nread = recv(s->sock_fd, read_buf, segment, flags); Py_END_ALLOW_THREADS if (timeout == 1) { - PyErr_SetString(socket_timeout, "timed out"); + PyErr_SetString(socketstate_global->socket_timeout, "timed out"); return -1; } END_SELECT_LOOP(s) @@ -2834,7 +2873,7 @@ Py_END_ALLOW_THREADS if (timeout == 1) { - PyErr_SetString(socket_timeout, "timed out"); + PyErr_SetString(socketstate_global->socket_timeout, "timed out"); return -1; } END_SELECT_LOOP(s) @@ -3022,7 +3061,7 @@ bytes_received = recvmsg(s->sock_fd, &msg, flags); Py_END_ALLOW_THREADS; if (timeout == 1) { - PyErr_SetString(socket_timeout, "timed out"); + PyErr_SetString(socketstate_global->socket_timeout, "timed out"); goto finally; } END_SELECT_LOOP(s) @@ -3312,7 +3351,7 @@ Py_END_ALLOW_THREADS if (timeout == 1) { PyBuffer_Release(&pbuf); - PyErr_SetString(socket_timeout, "timed out"); + PyErr_SetString(socketstate_global->socket_timeout, "timed out"); return NULL; } END_SELECT_LOOP(s) @@ -3365,7 +3404,7 @@ Py_END_ALLOW_THREADS if (timeout == 1) { PyBuffer_Release(&pbuf); - PyErr_SetString(socket_timeout, "timed out"); + PyErr_SetString(socketstate_global->socket_timeout, "timed out"); return NULL; } /* PyErr_CheckSignals() might change errno */ @@ -3458,7 +3497,7 @@ if (timeout == 1) { PyBuffer_Release(&pbuf); - PyErr_SetString(socket_timeout, "timed out"); + PyErr_SetString(socketstate_global->socket_timeout, "timed out"); return NULL; } END_SELECT_LOOP(s) @@ -3659,7 +3698,7 @@ bytes_sent = sendmsg(s->sock_fd, &msg, flags); Py_END_ALLOW_THREADS; if (timeout == 1) { - PyErr_SetString(socket_timeout, "timed out"); + PyErr_SetString(socketstate_global->socket_timeout, "timed out"); goto finally; } END_SELECT_LOOP(s) @@ -3887,6 +3926,7 @@ static void sock_dealloc(PySocketSockObject *s) { + PyTypeObject *type = Py_TYPE(s); if (s->sock_fd != -1) { PyObject *exc, *val, *tb; Py_ssize_t old_refcount = Py_REFCNT(s); @@ -3901,7 +3941,10 @@ (void) SOCKETCLOSE(s->sock_fd); Py_REFCNT(s) = old_refcount; } - Py_TYPE(s)->tp_free((PyObject *)s); + type->tp_free((PyObject *)s); + if((void *)type->tp_dealloc == (void *)sock_dealloc) { + Py_DECREF(type); + } } @@ -4017,48 +4060,32 @@ /* Type object for socket objects. */ -static PyTypeObject sock_type = { - PyVarObject_HEAD_INIT(0, 0) /* Must fill in type value later */ - "_socket.socket", /* tp_name */ - sizeof(PySocketSockObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)sock_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - (reprfunc)sock_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - sock_doc, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - sock_methods, /* tp_methods */ - sock_memberlist, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - sock_initobj, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ - sock_new, /* tp_new */ - PyObject_Del, /* tp_free */ + + + +static PyType_Slot sock_type_slots[] = { + {Py_tp_dealloc, (destructor)sock_dealloc}, + {Py_tp_repr, (reprfunc)sock_repr}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, sock_doc}, + {Py_tp_methods, sock_methods}, + {Py_tp_members, sock_memberlist}, + {Py_tp_init, sock_initobj}, + {Py_tp_alloc, PyType_GenericAlloc}, + {Py_tp_new, sock_new}, + {Py_tp_free, PyObject_Del}, + {0, 0} }; +static PyType_Spec sock_type_spec = { + "_socket.socket", + sizeof(PySocketSockObject), + 0, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + sock_type_slots, +}; + + /* Python interface to gethostname(). */ @@ -5549,7 +5576,7 @@ static PySocketModule_APIObject PySocketModuleAPI = { - &sock_type, + NULL, NULL, NULL }; @@ -5574,57 +5601,64 @@ PyModuleDef_HEAD_INIT, PySocket_MODULE_NAME, socket_doc, - -1, + sizeof(socketstate), socket_methods, NULL, - NULL, - NULL, - NULL + socket_traverse, + socket_clear, + socket_free }; PyMODINIT_FUNC PyInit__socket(void) { PyObject *m, *has_ipv6; + socketstate *state; if (!os_init()) return NULL; - Py_TYPE(&sock_type) = &PyType_Type; m = PyModule_Create(&socketmodule); if (m == NULL) return NULL; + state = socket_state(m); + + state->sock_type = PyType_FromSpec(&sock_type_spec); + if(state->sock_type == NULL) + return NULL; + + PySocketModuleAPI.Sock_Type = (PyTypeObject *)state->sock_type; Py_INCREF(PyExc_OSError); PySocketModuleAPI.error = PyExc_OSError; Py_INCREF(PyExc_OSError); PyModule_AddObject(m, "error", PyExc_OSError); - socket_herror = PyErr_NewException("socket.herror", + state->socket_herror = PyErr_NewException("socket.herror", PyExc_OSError, NULL); - if (socket_herror == NULL) + if (state->socket_herror == NULL) return NULL; - Py_INCREF(socket_herror); - PyModule_AddObject(m, "herror", socket_herror); - socket_gaierror = PyErr_NewException("socket.gaierror", PyExc_OSError, + Py_INCREF(state->socket_herror); + PyModule_AddObject(m, "herror", state->socket_herror); + state->socket_gaierror = PyErr_NewException("socket.gaierror", PyExc_OSError, NULL); - if (socket_gaierror == NULL) + if (state->socket_gaierror == NULL) return NULL; - Py_INCREF(socket_gaierror); - PyModule_AddObject(m, "gaierror", socket_gaierror); - socket_timeout = PyErr_NewException("socket.timeout", + Py_INCREF(state->socket_gaierror); + PyModule_AddObject(m, "gaierror", state->socket_gaierror); + state->socket_timeout = PyErr_NewException("socket.timeout", PyExc_OSError, NULL); - if (socket_timeout == NULL) + if (state->socket_timeout == NULL) return NULL; - PySocketModuleAPI.timeout_error = socket_timeout; - Py_INCREF(socket_timeout); - PyModule_AddObject(m, "timeout", socket_timeout); - Py_INCREF((PyObject *)&sock_type); + PySocketModuleAPI.timeout_error = state->socket_timeout; + Py_INCREF(state->socket_timeout); + PyModule_AddObject(m, "timeout", state->socket_timeout); + Py_INCREF(state->sock_type); if (PyModule_AddObject(m, "SocketType", - (PyObject *)&sock_type) != 0) + state->sock_type) != 0) return NULL; - Py_INCREF((PyObject *)&sock_type); + Py_INCREF(state->sock_type); if (PyModule_AddObject(m, "socket", - (PyObject *)&sock_type) != 0) + state->sock_type) != 0) return NULL; #ifdef ENABLE_IPV6