blob: dfc765c498f9b799cf9d4307ecea41bd0d2ca52a [file] [log] [blame]
Guido van Rossumed233a51992-06-23 09:07:03 +00001/***********************************************************
Guido van Rossum524b5881995-01-04 19:10:35 +00002Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
Guido van Rossumed233a51992-06-23 09:07:03 +00004
5 All Rights Reserved
6
Guido van Rossumd266eb41996-10-25 14:44:06 +00007Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
Guido van Rossumed233a51992-06-23 09:07:03 +00009provided that the above copyright notice appear in all copies and that
Guido van Rossumd266eb41996-10-25 14:44:06 +000010both that copyright notice and this permission notice appear in
Guido van Rossumed233a51992-06-23 09:07:03 +000011supporting documentation, and that the names of Stichting Mathematisch
Guido van Rossumd266eb41996-10-25 14:44:06 +000012Centrum or CWI or Corporation for National Research Initiatives or
13CNRI not be used in advertising or publicity pertaining to
14distribution of the software without specific, written prior
15permission.
Guido van Rossumed233a51992-06-23 09:07:03 +000016
Guido van Rossumd266eb41996-10-25 14:44:06 +000017While CWI is the initial source for this software, a modified version
18is made available by the Corporation for National Research Initiatives
19(CNRI) at the Internet address ftp://ftp.python.org.
20
21STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28PERFORMANCE OF THIS SOFTWARE.
Guido van Rossumed233a51992-06-23 09:07:03 +000029
30******************************************************************/
31
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000032/* select - Module containing unix select(2) call.
Barry Warsawe4ac0aa1996-12-12 00:04:35 +000033 Under Unix, the file descriptors are small integers.
34 Under Win32, select only exists for sockets, and sockets may
35 have any value except INVALID_SOCKET.
Guido van Rossumbcc20741998-08-04 22:53:56 +000036 Under BeOS, we suffer the same dichotomy as Win32; sockets can be anything
37 >= 0.
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000038*/
Guido van Rossumed233a51992-06-23 09:07:03 +000039
Barry Warsawe4ac0aa1996-12-12 00:04:35 +000040#include "Python.h"
Guido van Rossumed233a51992-06-23 09:07:03 +000041
Guido van Rossuma376cc51996-12-05 23:43:35 +000042#ifdef HAVE_UNISTD_H
43#include <unistd.h>
44#endif
45
Guido van Rossum37273171996-12-09 18:47:43 +000046#ifdef __sgi
47/* This is missing from unistd.h */
48extern void bzero();
49#endif
50
Guido van Rossumb6775db1994-08-01 11:34:53 +000051#include <sys/types.h>
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000052
Guido van Rossum8e9ebfd1997-11-22 21:53:48 +000053#if defined(PYOS_OS2)
54#include <sys/time.h>
55#include <utils.h>
56#endif
57
Guido van Rossum6f489d91996-06-28 20:15:15 +000058#ifdef MS_WINDOWS
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000059#include <winsock.h>
60#else
Guido van Rossumbcc20741998-08-04 22:53:56 +000061#ifdef __BEOS__
62#include <net/socket.h>
63#define SOCKET int
64#else
Guido van Rossumb6775db1994-08-01 11:34:53 +000065#include "myselect.h" /* Also includes mytime.h */
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000066#define SOCKET int
67#endif
Guido van Rossumbcc20741998-08-04 22:53:56 +000068#endif
Guido van Rossumed233a51992-06-23 09:07:03 +000069
Barry Warsawe4ac0aa1996-12-12 00:04:35 +000070static PyObject *SelectError;
Guido van Rossumed233a51992-06-23 09:07:03 +000071
Barry Warsawc1cb3601996-12-12 22:16:21 +000072/* list of Python objects and their file descriptor */
73typedef struct {
74 PyObject *obj; /* owned reference */
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000075 SOCKET fd;
Barry Warsawc1cb3601996-12-12 22:16:21 +000076 int sentinel; /* -1 == sentinel */
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000077} pylist;
78
Barry Warsawc1cb3601996-12-12 22:16:21 +000079static void
80reap_obj(fd2obj)
81 pylist fd2obj[FD_SETSIZE + 3];
82{
83 int i;
84 for (i = 0; i < FD_SETSIZE + 3 && fd2obj[i].sentinel >= 0; i++) {
85 Py_XDECREF(fd2obj[i].obj);
86 fd2obj[i].obj = NULL;
87 }
88 fd2obj[0].sentinel = -1;
89}
90
91
Barry Warsawe4ac0aa1996-12-12 00:04:35 +000092/* returns -1 and sets the Python exception if an error occurred, otherwise
93 returns a number >= 0
94*/
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000095static int
Guido van Rossum4fbf7981992-08-04 09:13:45 +000096list2set(list, set, fd2obj)
Barry Warsawe4ac0aa1996-12-12 00:04:35 +000097 PyObject *list;
98 fd_set *set;
99 pylist fd2obj[FD_SETSIZE + 3];
Guido van Rossumed233a51992-06-23 09:07:03 +0000100{
Barry Warsawc1cb3601996-12-12 22:16:21 +0000101 int i;
102 int max = -1;
103 int index = 0;
104 int len = PyList_Size(list);
105 PyObject* o = NULL;
Guido van Rossum07432c01995-03-29 16:47:45 +0000106
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000107 fd2obj[0].obj = (PyObject*)0; /* set list to zero size */
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000108 FD_ZERO(set);
Barry Warsawc1cb3601996-12-12 22:16:21 +0000109
110 for (i = 0; i < len; i++) {
111 PyObject *meth;
112 SOCKET v;
113
114 /* any intervening fileno() calls could decr this refcnt */
Barry Warsaw24c4b3d1996-12-13 23:22:42 +0000115 if (!(o = PyList_GetItem(list, i)))
Barry Warsaw529fcfe1996-12-16 18:15:34 +0000116 return -1;
Barry Warsaw24c4b3d1996-12-13 23:22:42 +0000117
Barry Warsawc1cb3601996-12-12 22:16:21 +0000118 Py_INCREF(o);
119
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000120 if (PyInt_Check(o)) {
121 v = PyInt_AsLong(o);
122 }
123 else if ((meth = PyObject_GetAttrString(o, "fileno")) != NULL)
124 {
Barry Warsawc1cb3601996-12-12 22:16:21 +0000125 PyObject *fno = PyEval_CallObject(meth, NULL);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000126 Py_DECREF(meth);
127 if (fno == NULL)
Barry Warsawc1cb3601996-12-12 22:16:21 +0000128 goto finally;
129
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000130 if (!PyInt_Check(fno)) {
Barry Warsawc1cb3601996-12-12 22:16:21 +0000131 PyErr_SetString(PyExc_TypeError,
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000132 "fileno method returned a non-integer");
Barry Warsawc1cb3601996-12-12 22:16:21 +0000133 Py_DECREF(fno);
134 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000135 }
136 v = PyInt_AsLong(fno);
137 Py_DECREF(fno);
138 }
139 else {
140 PyErr_SetString(PyExc_TypeError,
Barry Warsawc1cb3601996-12-12 22:16:21 +0000141 "argument must be an int, or have a fileno() method.");
142 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000143 }
Guido van Rossumbcc20741998-08-04 22:53:56 +0000144#if defined(_MSC_VER) || defined(__BEOS__)
Barry Warsawc1cb3601996-12-12 22:16:21 +0000145 max = 0; /* not used for Win32 */
146#else /* !_MSC_VER */
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000147 if (v < 0 || v >= FD_SETSIZE) {
Barry Warsawc1cb3601996-12-12 22:16:21 +0000148 PyErr_SetString(PyExc_ValueError,
149 "filedescriptor out of range in select()");
150 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000151 }
152 if (v > max)
153 max = v;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000154#endif /* _MSC_VER */
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000155 FD_SET(v, set);
Barry Warsawc1cb3601996-12-12 22:16:21 +0000156
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000157 /* add object and its file descriptor to the list */
158 if (index >= FD_SETSIZE) {
Barry Warsawc1cb3601996-12-12 22:16:21 +0000159 PyErr_SetString(PyExc_ValueError,
160 "too many file descriptors in select()");
161 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000162 }
163 fd2obj[index].obj = o;
164 fd2obj[index].fd = v;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000165 fd2obj[index].sentinel = 0;
166 fd2obj[++index].sentinel = -1;
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000167 }
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000168 return max+1;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000169
170 finally:
171 Py_XDECREF(o);
172 return -1;
Guido van Rossumed233a51992-06-23 09:07:03 +0000173}
174
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000175/* returns NULL and sets the Python exception if an error occurred */
176static PyObject *
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000177set2list(set, fd2obj)
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000178 fd_set *set;
179 pylist fd2obj[FD_SETSIZE + 3];
Guido van Rossumed233a51992-06-23 09:07:03 +0000180{
Barry Warsawc1cb3601996-12-12 22:16:21 +0000181 int i, j, count=0;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000182 PyObject *list, *o;
183 SOCKET fd;
Guido van Rossumed233a51992-06-23 09:07:03 +0000184
Barry Warsawc1cb3601996-12-12 22:16:21 +0000185 for (j = 0; fd2obj[j].sentinel >= 0; j++) {
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000186 if (FD_ISSET(fd2obj[j].fd, set))
Barry Warsawc1cb3601996-12-12 22:16:21 +0000187 count++;
188 }
189 list = PyList_New(count);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000190 if (!list)
191 return NULL;
192
Barry Warsawc1cb3601996-12-12 22:16:21 +0000193 i = 0;
194 for (j = 0; fd2obj[j].sentinel >= 0; j++) {
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000195 fd = fd2obj[j].fd;
196 if (FD_ISSET(fd, set)) {
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000197#ifndef _MSC_VER
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000198 if (fd > FD_SETSIZE) {
199 PyErr_SetString(PyExc_SystemError,
200 "filedescriptor out of range returned in select()");
Barry Warsawc1cb3601996-12-12 22:16:21 +0000201 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000202 }
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000203#endif
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000204 o = fd2obj[j].obj;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000205 fd2obj[j].obj = NULL;
206 /* transfer ownership */
207 if (PyList_SetItem(list, i, o) < 0)
208 goto finally;
209
210 i++;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000211 }
212 }
213 return list;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000214 finally:
215 Py_DECREF(list);
216 return NULL;
Guido van Rossumed233a51992-06-23 09:07:03 +0000217}
Barry Warsawc1cb3601996-12-12 22:16:21 +0000218
Guido van Rossumed233a51992-06-23 09:07:03 +0000219
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000220static PyObject *
Guido van Rossumed233a51992-06-23 09:07:03 +0000221select_select(self, args)
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000222 PyObject *self;
223 PyObject *args;
Guido van Rossumed233a51992-06-23 09:07:03 +0000224{
Guido van Rossumd20781b1998-07-02 02:53:36 +0000225#ifdef MS_WINDOWS
226 /* This would be an awful lot of stack space on Windows! */
227 pylist *rfd2obj, *wfd2obj, *efd2obj;
228#else
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000229 pylist rfd2obj[FD_SETSIZE + 3];
230 pylist wfd2obj[FD_SETSIZE + 3];
231 pylist efd2obj[FD_SETSIZE + 3];
Guido van Rossumd20781b1998-07-02 02:53:36 +0000232#endif
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000233 PyObject *ifdlist, *ofdlist, *efdlist;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000234 PyObject *ret = NULL;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000235 PyObject *tout = Py_None;
236 fd_set ifdset, ofdset, efdset;
237 double timeout;
238 struct timeval tv, *tvp;
239 int seconds;
240 int imax, omax, emax, max;
241 int n;
Guido van Rossumed233a51992-06-23 09:07:03 +0000242
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000243 /* convert arguments */
244 if (!PyArg_ParseTuple(args, "OOO|O",
245 &ifdlist, &ofdlist, &efdlist, &tout))
246 return NULL;
Guido van Rossumed233a51992-06-23 09:07:03 +0000247
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000248 if (tout == Py_None)
249 tvp = (struct timeval *)0;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000250 else if (!PyArg_Parse(tout, "d", &timeout)) {
251 PyErr_SetString(PyExc_TypeError,
252 "timeout must be a float or None");
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000253 return NULL;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000254 }
Guido van Rossumc7a22701993-11-01 16:27:16 +0000255 else {
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000256 seconds = (int)timeout;
257 timeout = timeout - (double)seconds;
258 tv.tv_sec = seconds;
259 tv.tv_usec = (int)(timeout*1000000.0);
260 tvp = &tv;
Guido van Rossumc7a22701993-11-01 16:27:16 +0000261 }
Guido van Rossumed233a51992-06-23 09:07:03 +0000262
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000263 /* sanity check first three arguments */
264 if (!PyList_Check(ifdlist) ||
265 !PyList_Check(ofdlist) ||
266 !PyList_Check(efdlist))
267 {
268 PyErr_SetString(PyExc_TypeError,
269 "arguments 1-3 must be lists");
270 return NULL;
271 }
Guido van Rossumed233a51992-06-23 09:07:03 +0000272
Guido van Rossumd20781b1998-07-02 02:53:36 +0000273#ifdef MS_WINDOWS
274 /* Allocate memory for the lists */
275 rfd2obj = PyMem_NEW(pylist, FD_SETSIZE + 3);
276 wfd2obj = PyMem_NEW(pylist, FD_SETSIZE + 3);
277 efd2obj = PyMem_NEW(pylist, FD_SETSIZE + 3);
278 if (rfd2obj == NULL || wfd2obj == NULL || efd2obj == NULL) {
279 PyMem_XDEL(rfd2obj);
280 PyMem_XDEL(wfd2obj);
281 PyMem_XDEL(efd2obj);
282 return NULL;
283 }
284#endif
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000285 /* Convert lists to fd_sets, and get maximum fd number
286 * propagates the Python exception set in list2set()
287 */
Barry Warsawc1cb3601996-12-12 22:16:21 +0000288 rfd2obj[0].sentinel = -1;
289 wfd2obj[0].sentinel = -1;
290 efd2obj[0].sentinel = -1;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000291 if ((imax=list2set(ifdlist, &ifdset, rfd2obj)) < 0)
Barry Warsawc1cb3601996-12-12 22:16:21 +0000292 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000293 if ((omax=list2set(ofdlist, &ofdset, wfd2obj)) < 0)
Barry Warsawc1cb3601996-12-12 22:16:21 +0000294 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000295 if ((emax=list2set(efdlist, &efdset, efd2obj)) < 0)
Barry Warsawc1cb3601996-12-12 22:16:21 +0000296 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000297 max = imax;
298 if (omax > max) max = omax;
299 if (emax > max) max = emax;
Guido van Rossumed233a51992-06-23 09:07:03 +0000300
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000301 Py_BEGIN_ALLOW_THREADS
302 n = select(max, &ifdset, &ofdset, &efdset, tvp);
303 Py_END_ALLOW_THREADS
Guido van Rossumed233a51992-06-23 09:07:03 +0000304
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000305 if (n < 0) {
306 PyErr_SetFromErrno(SelectError);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000307 }
Barry Warsawc1cb3601996-12-12 22:16:21 +0000308 else if (n == 0) {
309 /* optimization */
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000310 ifdlist = PyList_New(0);
Barry Warsawc1cb3601996-12-12 22:16:21 +0000311 if (ifdlist) {
312 ret = Py_BuildValue("OOO", ifdlist, ifdlist, ifdlist);
313 Py_DECREF(ifdlist);
314 }
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000315 }
Barry Warsawc1cb3601996-12-12 22:16:21 +0000316 else {
317 /* any of these three calls can raise an exception. it's more
318 convenient to test for this after all three calls... but
319 is that acceptable?
320 */
321 ifdlist = set2list(&ifdset, rfd2obj);
322 ofdlist = set2list(&ofdset, wfd2obj);
323 efdlist = set2list(&efdset, efd2obj);
324 if (PyErr_Occurred())
325 ret = NULL;
326 else
327 ret = Py_BuildValue("OOO", ifdlist, ofdlist, efdlist);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000328
Barry Warsawc1cb3601996-12-12 22:16:21 +0000329 Py_DECREF(ifdlist);
330 Py_DECREF(ofdlist);
331 Py_DECREF(efdlist);
332 }
333
334 finally:
335 reap_obj(rfd2obj);
336 reap_obj(wfd2obj);
337 reap_obj(efd2obj);
Guido van Rossumd20781b1998-07-02 02:53:36 +0000338#ifdef MS_WINDOWS
339 PyMem_DEL(rfd2obj);
340 PyMem_DEL(wfd2obj);
341 PyMem_DEL(efd2obj);
342#endif
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000343 return ret;
Guido van Rossumed233a51992-06-23 09:07:03 +0000344}
345
Guido van Rossum1d8fb2d1998-06-28 16:54:49 +0000346static char select_doc[] =
347"select(rlist, wlist, xlist[, timeout]) -> (rlist, wlist, xlist)\n\
348\n\
349Wait until one or more file descriptors are ready for some kind of I/O.\n\
350The first three arguments are lists of file descriptors to be waited for:\n\
351rlist -- wait until ready for reading\n\
352wlist -- wait until ready for writing\n\
353xlist -- wait for an ``exceptional condition''\n\
354If only one kind of condition is required, pass [] for the other lists.\n\
355A file descriptor is either a socket or file object, or a small integer\n\
356gotten from a fileno() method call on one of those.\n\
357\n\
358The optional 4th argument specifies a timeout in seconds; it may be\n\
359a floating point number to specify fractions of seconds. If it is absent\n\
360or None, the call will never time out.\n\
361\n\
362The return value is a tuple of three lists corresponding to the first three\n\
363arguments; each contains the subset of the corresponding file descriptors\n\
364that are ready.\n\
365\n\
366*** IMPORTANT NOTICE ***\n\
367On Windows, only sockets are supported; on Unix, all file descriptors.";
368
Guido van Rossumed233a51992-06-23 09:07:03 +0000369
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000370static PyMethodDef select_methods[] = {
Guido van Rossum1d8fb2d1998-06-28 16:54:49 +0000371 {"select", select_select, 1, select_doc},
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000372 {0, 0}, /* sentinel */
Guido van Rossumed233a51992-06-23 09:07:03 +0000373};
374
Guido van Rossum1d8fb2d1998-06-28 16:54:49 +0000375static char module_doc[] =
376"This module supports asynchronous I/O on multiple file descriptors.\n\
377\n\
378*** IMPORTANT NOTICE ***\n\
379On Windows, only sockets are supported; on Unix, all file descriptors.";
Guido van Rossumed233a51992-06-23 09:07:03 +0000380
381void
382initselect()
383{
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000384 PyObject *m, *d;
Guido van Rossum1d8fb2d1998-06-28 16:54:49 +0000385 m = Py_InitModule3("select", select_methods, module_doc);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000386 d = PyModule_GetDict(m);
Guido van Rossum0cb96de1997-10-01 04:29:29 +0000387 SelectError = PyErr_NewException("select.error", NULL, NULL);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000388 PyDict_SetItemString(d, "error", SelectError);
Guido van Rossumed233a51992-06-23 09:07:03 +0000389}