From b1ea11140af308efbcd2e9407c2f1ad9ddfbc06f Mon Sep 17 00:00:00 2001 From: Andrei Zene Date: Wed, 5 Jun 2019 15:30:30 +0300 Subject: [PATCH 1/6] Raise FD_SETSIZE limit to 16384 --- Modules/selectmodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c index ed71d8b0d59852..d484bb7009f7c1 100644 --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -33,7 +33,7 @@ FD_SETSIZE higher before this; e.g., via compiler /D switch. */ #if defined(MS_WINDOWS) && !defined(FD_SETSIZE) -#define FD_SETSIZE 512 +#define FD_SETSIZE 16384 #endif #if defined(HAVE_POLL_H) From c2e6ef03b4fab074cee51fd9cf61c486421d59de Mon Sep 17 00:00:00 2001 From: Andrei Zene Date: Mon, 10 Jun 2019 15:15:59 +0300 Subject: [PATCH 2/6] Dynamically allocate select fd_sets on Windows based on inputs list size --- Modules/selectmodule.c | 149 +++++++++++++++++++++++++++-------------- 1 file changed, 100 insertions(+), 49 deletions(-) diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c index d484bb7009f7c1..676aae91e14c3a 100644 --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -33,7 +33,7 @@ FD_SETSIZE higher before this; e.g., via compiler /D switch. */ #if defined(MS_WINDOWS) && !defined(FD_SETSIZE) -#define FD_SETSIZE 16384 +#define FD_SETSIZE 512 #endif #if defined(HAVE_POLL_H) @@ -58,6 +58,11 @@ extern void bzero(void *, int); # define SOCKET int #endif +#define FD_SET_PRIV(fd, set, setsize) do { \ + if (((fd_set FAR *)(set))->fd_count < setsize) \ + ((fd_set FAR *)(set))->fd_array[((fd_set FAR *)(set))->fd_count++]=(fd);\ +} while(0) + /*[clinic input] module select class select.poll "pollObject *" "&poll_Type" @@ -94,24 +99,37 @@ typedef struct { } pylist; static void -reap_obj(pylist fd2obj[FD_SETSIZE + 1]) +reap_obj(pylist *fd2obj, size_t setsize) { - unsigned int i; - for (i = 0; i < (unsigned int)FD_SETSIZE + 1 && fd2obj[i].sentinel >= 0; i++) { + size_t i; + for (i = 0; i < setsize + 1 && fd2obj[i].sentinel >= 0; i++) { Py_CLEAR(fd2obj[i].obj); } fd2obj[0].sentinel = -1; } +/* returns the size of a given Python sequence + returns -1 if the input is not a sequence +*/ +static Py_ssize_t +seqsize(PyObject *seq) +{ + PyObject* fast_seq = PySequence_Fast(seq, "argument 1 must be sequence"); + if (!fast_seq) + return -1; + + return PySequence_Fast_GET_SIZE(fast_seq); +} + /* returns -1 and sets the Python exception if an error occurred, otherwise returns a number >= 0 */ static int -seq2set(PyObject *seq, fd_set *set, pylist fd2obj[FD_SETSIZE + 1]) +seq2set(PyObject *seq, fd_set *set, pylist *fd2obj, size_t setsize) { int max = -1; - unsigned int index = 0; + size_t index = 0; Py_ssize_t i; PyObject* fast_seq = NULL; PyObject* o = NULL; @@ -145,10 +163,10 @@ seq2set(PyObject *seq, fd_set *set, pylist fd2obj[FD_SETSIZE + 1]) if (v > max) max = v; #endif /* _MSC_VER */ - FD_SET(v, set); + FD_SET_PRIV(v, set, setsize); /* add object and its file descriptor to the list */ - if (index >= (unsigned int)FD_SETSIZE) { + if (index >= setsize) { PyErr_SetString(PyExc_ValueError, "too many file descriptors in select()"); goto finally; @@ -169,13 +187,13 @@ seq2set(PyObject *seq, fd_set *set, pylist fd2obj[FD_SETSIZE + 1]) /* returns NULL and sets the Python exception if an error occurred */ static PyObject * -set2list(fd_set *set, pylist fd2obj[FD_SETSIZE + 1]) +set2list(fd_set *set, pylist *fd2obj, size_t setsize) { - int i, j, count=0; + size_t i, j, count=0; PyObject *list, *o; SOCKET fd; - for (j = 0; fd2obj[j].sentinel >= 0; j++) { + for (j = 0; j < setsize && fd2obj[j].sentinel >= 0; j++) { if (FD_ISSET(fd2obj[j].fd, set)) count++; } @@ -184,7 +202,7 @@ set2list(fd_set *set, pylist fd2obj[FD_SETSIZE + 1]) return NULL; i = 0; - for (j = 0; fd2obj[j].sentinel >= 0; j++) { + for (j = 0; j < setsize && fd2obj[j].sentinel >= 0; j++) { fd = fd2obj[j].fd; if (FD_ISSET(fd, set)) { o = fd2obj[j].obj; @@ -202,10 +220,6 @@ set2list(fd_set *set, pylist fd2obj[FD_SETSIZE + 1]) return NULL; } -#undef SELECT_USES_HEAP -#if FD_SETSIZE > 1024 -#define SELECT_USES_HEAP -#endif /* FD_SETSIZE > 1024 */ /*[clinic input] select.select @@ -245,25 +259,34 @@ select_select_impl(PyObject *module, PyObject *rlist, PyObject *wlist, PyObject *xlist, PyObject *timeout_obj) /*[clinic end generated code: output=2b3cfa824f7ae4cf input=177e72184352df25]*/ { -#ifdef SELECT_USES_HEAP + size_t setsize; pylist *rfd2obj, *wfd2obj, *efd2obj; -#else /* !SELECT_USES_HEAP */ - /* XXX: All this should probably be implemented as follows: - * - find the highest descriptor we're interested in - * - add one - * - that's the size - * See: Stevens, APitUE, $12.5.1 - */ - pylist rfd2obj[FD_SETSIZE + 1]; - pylist wfd2obj[FD_SETSIZE + 1]; - pylist efd2obj[FD_SETSIZE + 1]; -#endif /* SELECT_USES_HEAP */ PyObject *ret = NULL; - fd_set ifdset, ofdset, efdset; + fd_set *ifdset, *ofdset, *efdset; +#if !defined(MS_WINDOWS) + fd_set ifdset_stack, ofdset_stack, efdset_stack; + pylist rfd2obj_stack[FD_SETSIZE + 1]; + pylist wfd2obj_stack[FD_SETSIZE + 1]; + pylist efd2obj_stack[FD_SETSIZE + 1]; +#endif struct timeval tv, *tvp; int imax, omax, emax, max; int n; _PyTime_t timeout, deadline = 0; + Py_ssize_t rsize, wsize, xsize; + + setsize = FD_SETSIZE; +#if defined(MS_WINDOWS) + /* On windows we allocated the fd sets dynamically + based on the inputs size */ + rsize = seqsize(rlist); + wsize = seqsize(wlist); + xsize = seqsize(xlist); + + if (rsize > (Py_ssize_t)setsize) setsize = (size_t)rsize; + if (wsize > (Py_ssize_t)setsize) setsize = (size_t)wsize; + if (xsize > (Py_ssize_t)setsize) setsize = (size_t)xsize; +#endif if (timeout_obj == Py_None) tvp = (struct timeval *)NULL; @@ -286,18 +309,43 @@ select_select_impl(PyObject *module, PyObject *rlist, PyObject *wlist, tvp = &tv; } -#ifdef SELECT_USES_HEAP +#if defined(MS_WINDOWS) /* Allocate memory for the lists */ - rfd2obj = PyMem_NEW(pylist, FD_SETSIZE + 1); - wfd2obj = PyMem_NEW(pylist, FD_SETSIZE + 1); - efd2obj = PyMem_NEW(pylist, FD_SETSIZE + 1); + rfd2obj = PyMem_NEW(pylist, setsize + 1); + wfd2obj = PyMem_NEW(pylist, setsize + 1); + efd2obj = PyMem_NEW(pylist, setsize + 1); if (rfd2obj == NULL || wfd2obj == NULL || efd2obj == NULL) { if (rfd2obj) PyMem_DEL(rfd2obj); if (wfd2obj) PyMem_DEL(wfd2obj); if (efd2obj) PyMem_DEL(efd2obj); return PyErr_NoMemory(); } -#endif /* SELECT_USES_HEAP */ +#else + rfd2obj = &rfd2obj_stack; + wfd2obj = &wfd2obj_stack; + efd2obj = &efd2obj_stack; +#endif + +#if defined(MS_WINDOWS) + /* Allocate memory for the sets */ + /* We ought to allocate setsize * sizeof(SOCKET) + + sizeof(int) bytes. With this approach on 64-bit we + allocate 4 additional unused bytes but the allocation + code looks a lot simpler.*/ + ifdset = (fd_set*) PyMem_NEW(SOCKET, setsize + 1); + ofdset = (fd_set*) PyMem_NEW(SOCKET, setsize + 1); + efdset = (fd_set*) PyMem_NEW(SOCKET, setsize + 1); + if (ifdset->fd_array == NULL || ofdset->fd_array == NULL || efdset->fd_array == NULL) { + if (ifdset->fd_array) PyMem_DEL(ifdset->fd_array); + if (ofdset->fd_array) PyMem_DEL(ofdset->fd_array); + if (efdset->fd_array) PyMem_DEL(efdset->fd_array); + return PyErr_NoMemory(); + } +#else + ifdset = &ifdset_stack; + ofdset = &ofdset_stack; + efdset = &efdset_stack; +#endif /* Convert sequences to fd_sets, and get maximum fd number * propagates the Python exception set in seq2set() @@ -305,11 +353,11 @@ select_select_impl(PyObject *module, PyObject *rlist, PyObject *wlist, rfd2obj[0].sentinel = -1; wfd2obj[0].sentinel = -1; efd2obj[0].sentinel = -1; - if ((imax = seq2set(rlist, &ifdset, rfd2obj)) < 0) + if ((imax = seq2set(rlist, ifdset, rfd2obj, setsize)) < 0) goto finally; - if ((omax = seq2set(wlist, &ofdset, wfd2obj)) < 0) + if ((omax = seq2set(wlist, ofdset, wfd2obj, setsize)) < 0) goto finally; - if ((emax = seq2set(xlist, &efdset, efd2obj)) < 0) + if ((emax = seq2set(xlist, efdset, efd2obj, setsize)) < 0) goto finally; max = imax; @@ -322,7 +370,7 @@ select_select_impl(PyObject *module, PyObject *rlist, PyObject *wlist, do { Py_BEGIN_ALLOW_THREADS errno = 0; - n = select(max, &ifdset, &ofdset, &efdset, tvp); + n = select(max, ifdset, ofdset, efdset, tvp); Py_END_ALLOW_THREADS if (errno != EINTR) @@ -336,9 +384,9 @@ select_select_impl(PyObject *module, PyObject *rlist, PyObject *wlist, timeout = deadline - _PyTime_GetMonotonicClock(); if (timeout < 0) { /* bpo-35310: lists were unmodified -- clear them explicitly */ - FD_ZERO(&ifdset); - FD_ZERO(&ofdset); - FD_ZERO(&efdset); + FD_ZERO(ifdset); + FD_ZERO(ofdset); + FD_ZERO(efdset); n = 0; break; } @@ -361,9 +409,9 @@ select_select_impl(PyObject *module, PyObject *rlist, PyObject *wlist, convenient to test for this after all three calls... but is that acceptable? */ - rlist = set2list(&ifdset, rfd2obj); - wlist = set2list(&ofdset, wfd2obj); - xlist = set2list(&efdset, efd2obj); + rlist = set2list(ifdset, rfd2obj, setsize); + wlist = set2list(ofdset, wfd2obj, setsize); + xlist = set2list(efdset, efd2obj, setsize); if (PyErr_Occurred()) ret = NULL; else @@ -375,14 +423,17 @@ select_select_impl(PyObject *module, PyObject *rlist, PyObject *wlist, } finally: - reap_obj(rfd2obj); - reap_obj(wfd2obj); - reap_obj(efd2obj); -#ifdef SELECT_USES_HEAP + reap_obj(rfd2obj, setsize); + reap_obj(wfd2obj, setsize); + reap_obj(efd2obj, setsize); +#if defined(MS_WINDOWS) PyMem_DEL(rfd2obj); PyMem_DEL(wfd2obj); PyMem_DEL(efd2obj); -#endif /* SELECT_USES_HEAP */ + PyMem_DEL(ifdset); + PyMem_DEL(ofdset); + PyMem_DEL(efdset); +#endif return ret; } From c19f865b87473c102907d48a53cf58153c0e295e Mon Sep 17 00:00:00 2001 From: Andrei Zene Date: Mon, 10 Jun 2019 16:44:25 +0300 Subject: [PATCH 3/6] Move new FD_SET macro definition under defined(MS_WINDOWS) --- Modules/selectmodule.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c index 676aae91e14c3a..69b1567282d0b0 100644 --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -58,10 +58,12 @@ extern void bzero(void *, int); # define SOCKET int #endif -#define FD_SET_PRIV(fd, set, setsize) do { \ +#if defined(MS_WINDOWS) +#define FD_SET_WIN(fd, set, setsize) do { \ if (((fd_set FAR *)(set))->fd_count < setsize) \ ((fd_set FAR *)(set))->fd_array[((fd_set FAR *)(set))->fd_count++]=(fd);\ } while(0) +#endif /*[clinic input] module select @@ -163,7 +165,7 @@ seq2set(PyObject *seq, fd_set *set, pylist *fd2obj, size_t setsize) if (v > max) max = v; #endif /* _MSC_VER */ - FD_SET_PRIV(v, set, setsize); + FD_SET_WIN(v, set, setsize); /* add object and its file descriptor to the list */ if (index >= setsize) { From 185db02262ae8fc0a194aeaced574e061210bb7c Mon Sep 17 00:00:00 2001 From: Andrei Zene Date: Mon, 10 Jun 2019 16:52:57 +0300 Subject: [PATCH 4/6] Added News file --- .../next/Library/2019-06-10-16-52-41.bpo-28708.rJO_YP.rst | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2019-06-10-16-52-41.bpo-28708.rJO_YP.rst diff --git a/Misc/NEWS.d/next/Library/2019-06-10-16-52-41.bpo-28708.rJO_YP.rst b/Misc/NEWS.d/next/Library/2019-06-10-16-52-41.bpo-28708.rJO_YP.rst new file mode 100644 index 00000000000000..351916f143ae52 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-06-10-16-52-41.bpo-28708.rJO_YP.rst @@ -0,0 +1,3 @@ +Made :func:`select.select dynamically allocate fd_set arrays on Windows, +based on size of inputs size. This basically removes the FD_SETSIZE +limitation on Windows. From 555f0e15bcdd0447bb43df8442d24e6ff368cf7f Mon Sep 17 00:00:00 2001 From: Andrei Zene Date: Mon, 10 Jun 2019 18:30:59 +0300 Subject: [PATCH 5/6] Fix linux & doc build --- .../2019-06-10-16-52-41.bpo-28708.rJO_YP.rst | 2 +- Modules/selectmodule.c | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/Misc/NEWS.d/next/Library/2019-06-10-16-52-41.bpo-28708.rJO_YP.rst b/Misc/NEWS.d/next/Library/2019-06-10-16-52-41.bpo-28708.rJO_YP.rst index 351916f143ae52..f33ba3b5702cbb 100644 --- a/Misc/NEWS.d/next/Library/2019-06-10-16-52-41.bpo-28708.rJO_YP.rst +++ b/Misc/NEWS.d/next/Library/2019-06-10-16-52-41.bpo-28708.rJO_YP.rst @@ -1,3 +1,3 @@ -Made :func:`select.select dynamically allocate fd_set arrays on Windows, +Made :func:`select.select` dynamically allocate fd_set arrays on Windows, based on size of inputs size. This basically removes the FD_SETSIZE limitation on Windows. diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c index 69b1567282d0b0..ca2cf4c455b797 100644 --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -165,7 +165,11 @@ seq2set(PyObject *seq, fd_set *set, pylist *fd2obj, size_t setsize) if (v > max) max = v; #endif /* _MSC_VER */ +#if defined(MS_WINDOWS) FD_SET_WIN(v, set, setsize); +#else + FD_SET(v, set); +#endif /* add object and its file descriptor to the list */ if (index >= setsize) { @@ -270,12 +274,13 @@ select_select_impl(PyObject *module, PyObject *rlist, PyObject *wlist, pylist rfd2obj_stack[FD_SETSIZE + 1]; pylist wfd2obj_stack[FD_SETSIZE + 1]; pylist efd2obj_stack[FD_SETSIZE + 1]; +#else + Py_ssize_t rsize, wsize, xsize; #endif struct timeval tv, *tvp; int imax, omax, emax, max; int n; _PyTime_t timeout, deadline = 0; - Py_ssize_t rsize, wsize, xsize; setsize = FD_SETSIZE; #if defined(MS_WINDOWS) @@ -323,9 +328,9 @@ select_select_impl(PyObject *module, PyObject *rlist, PyObject *wlist, return PyErr_NoMemory(); } #else - rfd2obj = &rfd2obj_stack; - wfd2obj = &wfd2obj_stack; - efd2obj = &efd2obj_stack; + rfd2obj = (pylist*)&rfd2obj_stack; + wfd2obj = (pylist*)&wfd2obj_stack; + efd2obj = (pylist*)&efd2obj_stack; #endif #if defined(MS_WINDOWS) From 35885cb98c63c6486a4ffb27980a906e69f9ad66 Mon Sep 17 00:00:00 2001 From: Andrei Zene Date: Fri, 14 Jun 2019 09:36:28 +0300 Subject: [PATCH 6/6] Add back SELECT_USES_HEAP --- .../2019-06-10-16-52-41.bpo-28708.rJO_YP.rst | 2 +- Modules/selectmodule.c | 73 ++++++++++--------- 2 files changed, 39 insertions(+), 36 deletions(-) diff --git a/Misc/NEWS.d/next/Library/2019-06-10-16-52-41.bpo-28708.rJO_YP.rst b/Misc/NEWS.d/next/Library/2019-06-10-16-52-41.bpo-28708.rJO_YP.rst index f33ba3b5702cbb..ec4ad5549be0bd 100644 --- a/Misc/NEWS.d/next/Library/2019-06-10-16-52-41.bpo-28708.rJO_YP.rst +++ b/Misc/NEWS.d/next/Library/2019-06-10-16-52-41.bpo-28708.rJO_YP.rst @@ -1,3 +1,3 @@ Made :func:`select.select` dynamically allocate fd_set arrays on Windows, -based on size of inputs size. This basically removes the FD_SETSIZE +based on size of inputs. This basically removes the FD_SETSIZE limitation on Windows. diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c index ca2cf4c455b797..e4b50bfd05a653 100644 --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -59,11 +59,15 @@ extern void bzero(void *, int); #endif #if defined(MS_WINDOWS) -#define FD_SET_WIN(fd, set, setsize) do { \ - if (((fd_set FAR *)(set))->fd_count < setsize) \ - ((fd_set FAR *)(set))->fd_array[((fd_set FAR *)(set))->fd_count++]=(fd);\ -} while(0) -#endif + +void fd_set_win(SOCKET fd, fd_set *set, size_t setsize) { + do { + if (((fd_set FAR *)(set))->fd_count < setsize) + ((fd_set FAR *)(set))->fd_array[((fd_set FAR *)(set))->fd_count++]=(fd); + } while(0); +} + +#endif /* defined(MS_WINDOWS) */ /*[clinic input] module select @@ -110,20 +114,6 @@ reap_obj(pylist *fd2obj, size_t setsize) fd2obj[0].sentinel = -1; } - -/* returns the size of a given Python sequence - returns -1 if the input is not a sequence -*/ -static Py_ssize_t -seqsize(PyObject *seq) -{ - PyObject* fast_seq = PySequence_Fast(seq, "argument 1 must be sequence"); - if (!fast_seq) - return -1; - - return PySequence_Fast_GET_SIZE(fast_seq); -} - /* returns -1 and sets the Python exception if an error occurred, otherwise returns a number >= 0 */ @@ -166,10 +156,10 @@ seq2set(PyObject *seq, fd_set *set, pylist *fd2obj, size_t setsize) max = v; #endif /* _MSC_VER */ #if defined(MS_WINDOWS) - FD_SET_WIN(v, set, setsize); + fd_set_win(v, set, setsize); #else FD_SET(v, set); -#endif +#endif /* defined(MS_WINDOWS) */ /* add object and its file descriptor to the list */ if (index >= setsize) { @@ -226,6 +216,10 @@ set2list(fd_set *set, pylist *fd2obj, size_t setsize) return NULL; } +#undef SELECT_USES_HEAP +#if FD_SETSIZE > 1024 +#define SELECT_USES_HEAP +#endif /* FD_SETSIZE > 1024 */ /*[clinic input] select.select @@ -271,12 +265,14 @@ select_select_impl(PyObject *module, PyObject *rlist, PyObject *wlist, fd_set *ifdset, *ofdset, *efdset; #if !defined(MS_WINDOWS) fd_set ifdset_stack, ofdset_stack, efdset_stack; +#if !defined(SELECT_USES_HEAP) pylist rfd2obj_stack[FD_SETSIZE + 1]; pylist wfd2obj_stack[FD_SETSIZE + 1]; pylist efd2obj_stack[FD_SETSIZE + 1]; +#endif /* !defined(SELECT_USES_HEAP) */ #else Py_ssize_t rsize, wsize, xsize; -#endif +#endif /* !defined(MS_WINDOWS) */ struct timeval tv, *tvp; int imax, omax, emax, max; int n; @@ -286,14 +282,19 @@ select_select_impl(PyObject *module, PyObject *rlist, PyObject *wlist, #if defined(MS_WINDOWS) /* On windows we allocated the fd sets dynamically based on the inputs size */ - rsize = seqsize(rlist); - wsize = seqsize(wlist); - xsize = seqsize(xlist); + rsize = PySequence_Length(rlist); + wsize = PySequence_Length(wlist); + xsize = PySequence_Length(xlist); - if (rsize > (Py_ssize_t)setsize) setsize = (size_t)rsize; - if (wsize > (Py_ssize_t)setsize) setsize = (size_t)wsize; - if (xsize > (Py_ssize_t)setsize) setsize = (size_t)xsize; -#endif + if (rsize < 0 || wsize < 0 || xsize < 0) { + PyErr_SetString(PyExc_ValueError, "arguments 1-3 must be sequences"); + return NULL; + } + + if ((size_t)rsize > setsize) setsize = (size_t)rsize; + if ((size_t)wsize > setsize) setsize = (size_t)wsize; + if ((size_t)xsize > setsize) setsize = (size_t)xsize; +#endif /* defined(MS_WINDOWS) */ if (timeout_obj == Py_None) tvp = (struct timeval *)NULL; @@ -316,7 +317,7 @@ select_select_impl(PyObject *module, PyObject *rlist, PyObject *wlist, tvp = &tv; } -#if defined(MS_WINDOWS) +#if defined(MS_WINDOWS) || defined(SELECT_USES_HEAP) /* Allocate memory for the lists */ rfd2obj = PyMem_NEW(pylist, setsize + 1); wfd2obj = PyMem_NEW(pylist, setsize + 1); @@ -327,11 +328,11 @@ select_select_impl(PyObject *module, PyObject *rlist, PyObject *wlist, if (efd2obj) PyMem_DEL(efd2obj); return PyErr_NoMemory(); } -#else +#else /* !defined(MS_WINDOWS) && !defined(SELECT_USES_HEAP) */ rfd2obj = (pylist*)&rfd2obj_stack; wfd2obj = (pylist*)&wfd2obj_stack; efd2obj = (pylist*)&efd2obj_stack; -#endif +#endif /* defined(MS_WINDOWS) || defined(SELECT_USES_HEAP) */ #if defined(MS_WINDOWS) /* Allocate memory for the sets */ @@ -352,7 +353,7 @@ select_select_impl(PyObject *module, PyObject *rlist, PyObject *wlist, ifdset = &ifdset_stack; ofdset = &ofdset_stack; efdset = &efdset_stack; -#endif +#endif /* defined(MS_WINDOWS) */ /* Convert sequences to fd_sets, and get maximum fd number * propagates the Python exception set in seq2set() @@ -433,14 +434,16 @@ select_select_impl(PyObject *module, PyObject *rlist, PyObject *wlist, reap_obj(rfd2obj, setsize); reap_obj(wfd2obj, setsize); reap_obj(efd2obj, setsize); -#if defined(MS_WINDOWS) +#if defined(MS_WINDOWS) || defined(SELECT_USES_HEAP) PyMem_DEL(rfd2obj); PyMem_DEL(wfd2obj); PyMem_DEL(efd2obj); +#endif /* defined(MS_WINDOWS) || defined(SELECT_USES_HEAP) */ +#if defined(MS_WINDOWS) PyMem_DEL(ifdset); PyMem_DEL(ofdset); PyMem_DEL(efdset); -#endif +#endif /* MS_WINDOWS */ return ret; }