diff -r f6c4c178da56 Modules/selectmodule.c --- a/Modules/selectmodule.c Sun Nov 11 14:01:23 2012 +0100 +++ b/Modules/selectmodule.c Sun Nov 11 23:48:21 2012 +0200 @@ -315,7 +315,8 @@ typedef struct { PyObject_HEAD PyObject *dict; - int ufd_uptodate; + int tag; + int ufd_tag; int ufd_len; struct pollfd *ufds; } pollObject; @@ -347,7 +348,7 @@ self->ufds[i].events = (short)PyInt_AsLong(value); i++; } - self->ufd_uptodate = 1; + self->ufd_tag = self->tag; return 1; } @@ -388,7 +389,7 @@ if (err < 0) return NULL; - self->ufd_uptodate = 0; + self->tag += 1; Py_INCREF(Py_None); return Py_None; @@ -435,7 +436,7 @@ if (err < 0) return NULL; - self->ufd_uptodate = 0; + self->tag += 1; Py_INCREF(Py_None); return Py_None; @@ -469,7 +470,7 @@ } Py_DECREF(key); - self->ufd_uptodate = 0; + self->tag += 1; Py_INCREF(Py_None); return Py_None; @@ -484,8 +485,9 @@ poll_poll(pollObject *self, PyObject *args) { PyObject *result_list = NULL, *tout = NULL; - int timeout = 0, poll_result, i, j; + int timeout = 0, poll_result, i, j, ufd_tag, ufd_len; PyObject *value = NULL, *num = NULL; + struct pollfd *ufds; if (!PyArg_UnpackTuple(args, "poll", 0, 1, &tout)) { return NULL; @@ -510,29 +512,32 @@ } /* Ensure the ufd array is up to date */ - if (!self->ufd_uptodate) + if (!self->ufds || (self->ufd_tag != self->tag)) if (update_ufd_array(self) == 0) return NULL; + ufd_tag = self->ufd_tag; + ufd_len = self->ufd_len; + ufds = self->ufds; + self->ufds = NULL; + /* call poll() */ Py_BEGIN_ALLOW_THREADS - poll_result = poll(self->ufds, self->ufd_len, timeout); + poll_result = poll(ufds, ufd_len, timeout); Py_END_ALLOW_THREADS if (poll_result < 0) { PyErr_SetFromErrno(SelectError); - return NULL; + goto done; } /* build the result list */ result_list = PyList_New(poll_result); - if (!result_list) - return NULL; - else { + if (result_list) { for (i = 0, j = 0; j < poll_result; j++) { /* skip to the next fired descriptor */ - while (!self->ufds[i].revents) { + while (!ufds[i].revents) { i++; } /* if we hit a NULL return, set value to NULL @@ -541,7 +546,7 @@ value = PyTuple_New(2); if (value == NULL) goto error; - num = PyInt_FromLong(self->ufds[i].fd); + num = PyInt_FromLong(ufds[i].fd); if (num == NULL) { Py_DECREF(value); goto error; @@ -552,7 +557,7 @@ is a 16-bit short, and IBM assigned POLLNVAL to be 0x8000, so the conversion to int results in a negative number. See SF bug #923315. */ - num = PyInt_FromLong(self->ufds[i].revents & 0xffff); + num = PyInt_FromLong(ufds[i].revents & 0xffff); if (num == NULL) { Py_DECREF(value); goto error; @@ -565,11 +570,19 @@ i++; } } + done: + if (self->ufds == NULL && self->tag == ufd_tag) { + self->ufds = ufds; + self->ufd_tag = ufd_tag; + self->ufd_len = ufd_len; + } else { + PyMem_FREE(ufds); + } return result_list; error: - Py_DECREF(result_list); - return NULL; + Py_CLEAR(result_list); + goto done; } static PyMethodDef poll_methods[] = { @@ -591,9 +604,10 @@ self = PyObject_New(pollObject, &poll_Type); if (self == NULL) return NULL; - /* ufd_uptodate is a Boolean, denoting whether the - array pointed to by ufds matches the contents of the dictionary. */ - self->ufd_uptodate = 0; + /* tag is an int which is incremented every time the dictionary is + updated; ufd_tag is the tag that currently belong to the ufds array + if ufds != NULL && tag == ufd_tag, then ufds is up-to-date */ + self->tag = 0; self->ufds = NULL; self->dict = PyDict_New(); if (self->dict == NULL) {