blob: 34300771987332fdb520e16bd4df63a22c2b9912 [file] [log] [blame]
Guido van Rossumed233a51992-06-23 09:07:03 +00001/***********************************************************
Guido van Rossumfd71b9e2000-06-30 23:50:40 +00002Copyright (c) 2000, BeOpen.com.
3Copyright (c) 1995-2000, Corporation for National Research Initiatives.
4Copyright (c) 1990-1995, Stichting Mathematisch Centrum.
5All rights reserved.
Guido van Rossumed233a51992-06-23 09:07:03 +00006
Guido van Rossumfd71b9e2000-06-30 23:50:40 +00007See the file "Misc/COPYRIGHT" for information on usage and
8redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
Guido van Rossumed233a51992-06-23 09:07:03 +00009******************************************************************/
10
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000011/* select - Module containing unix select(2) call.
Barry Warsawe4ac0aa1996-12-12 00:04:35 +000012 Under Unix, the file descriptors are small integers.
13 Under Win32, select only exists for sockets, and sockets may
14 have any value except INVALID_SOCKET.
Guido van Rossumbcc20741998-08-04 22:53:56 +000015 Under BeOS, we suffer the same dichotomy as Win32; sockets can be anything
16 >= 0.
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000017*/
Guido van Rossumed233a51992-06-23 09:07:03 +000018
Barry Warsawe4ac0aa1996-12-12 00:04:35 +000019#include "Python.h"
Guido van Rossumed233a51992-06-23 09:07:03 +000020
Guido van Rossuma376cc51996-12-05 23:43:35 +000021#ifdef HAVE_UNISTD_H
22#include <unistd.h>
23#endif
24
Guido van Rossum37273171996-12-09 18:47:43 +000025#ifdef __sgi
26/* This is missing from unistd.h */
27extern void bzero();
28#endif
29
Guido van Rossumff7e83d1999-08-27 20:39:37 +000030#ifndef DONT_HAVE_SYS_TYPES_H
Guido van Rossumb6775db1994-08-01 11:34:53 +000031#include <sys/types.h>
Guido van Rossumff7e83d1999-08-27 20:39:37 +000032#endif
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000033
Guido van Rossum8e9ebfd1997-11-22 21:53:48 +000034#if defined(PYOS_OS2)
35#include <sys/time.h>
36#include <utils.h>
37#endif
38
Guido van Rossum6f489d91996-06-28 20:15:15 +000039#ifdef MS_WINDOWS
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000040#include <winsock.h>
41#else
Guido van Rossumbcc20741998-08-04 22:53:56 +000042#ifdef __BEOS__
43#include <net/socket.h>
44#define SOCKET int
45#else
Guido van Rossumb6775db1994-08-01 11:34:53 +000046#include "myselect.h" /* Also includes mytime.h */
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000047#define SOCKET int
48#endif
Guido van Rossumbcc20741998-08-04 22:53:56 +000049#endif
Guido van Rossumed233a51992-06-23 09:07:03 +000050
Barry Warsawe4ac0aa1996-12-12 00:04:35 +000051static PyObject *SelectError;
Guido van Rossumed233a51992-06-23 09:07:03 +000052
Barry Warsawc1cb3601996-12-12 22:16:21 +000053/* list of Python objects and their file descriptor */
54typedef struct {
55 PyObject *obj; /* owned reference */
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000056 SOCKET fd;
Barry Warsawc1cb3601996-12-12 22:16:21 +000057 int sentinel; /* -1 == sentinel */
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000058} pylist;
59
Barry Warsawc1cb3601996-12-12 22:16:21 +000060static void
61reap_obj(fd2obj)
62 pylist fd2obj[FD_SETSIZE + 3];
63{
64 int i;
65 for (i = 0; i < FD_SETSIZE + 3 && fd2obj[i].sentinel >= 0; i++) {
66 Py_XDECREF(fd2obj[i].obj);
67 fd2obj[i].obj = NULL;
68 }
69 fd2obj[0].sentinel = -1;
70}
71
72
Barry Warsawe4ac0aa1996-12-12 00:04:35 +000073/* returns -1 and sets the Python exception if an error occurred, otherwise
74 returns a number >= 0
75*/
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000076static int
Guido van Rossum4fbf7981992-08-04 09:13:45 +000077list2set(list, set, fd2obj)
Barry Warsawe4ac0aa1996-12-12 00:04:35 +000078 PyObject *list;
79 fd_set *set;
80 pylist fd2obj[FD_SETSIZE + 3];
Guido van Rossumed233a51992-06-23 09:07:03 +000081{
Barry Warsawc1cb3601996-12-12 22:16:21 +000082 int i;
83 int max = -1;
84 int index = 0;
85 int len = PyList_Size(list);
86 PyObject* o = NULL;
Guido van Rossum07432c01995-03-29 16:47:45 +000087
Barry Warsawe4ac0aa1996-12-12 00:04:35 +000088 fd2obj[0].obj = (PyObject*)0; /* set list to zero size */
Barry Warsawe4ac0aa1996-12-12 00:04:35 +000089 FD_ZERO(set);
Barry Warsawc1cb3601996-12-12 22:16:21 +000090
91 for (i = 0; i < len; i++) {
92 PyObject *meth;
93 SOCKET v;
94
95 /* any intervening fileno() calls could decr this refcnt */
Barry Warsaw24c4b3d1996-12-13 23:22:42 +000096 if (!(o = PyList_GetItem(list, i)))
Barry Warsaw529fcfe1996-12-16 18:15:34 +000097 return -1;
Barry Warsaw24c4b3d1996-12-13 23:22:42 +000098
Barry Warsawc1cb3601996-12-12 22:16:21 +000099 Py_INCREF(o);
100
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000101 if (PyInt_Check(o)) {
102 v = PyInt_AsLong(o);
103 }
104 else if ((meth = PyObject_GetAttrString(o, "fileno")) != NULL)
105 {
Barry Warsawc1cb3601996-12-12 22:16:21 +0000106 PyObject *fno = PyEval_CallObject(meth, NULL);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000107 Py_DECREF(meth);
108 if (fno == NULL)
Barry Warsawc1cb3601996-12-12 22:16:21 +0000109 goto finally;
110
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000111 if (!PyInt_Check(fno)) {
Barry Warsawc1cb3601996-12-12 22:16:21 +0000112 PyErr_SetString(PyExc_TypeError,
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000113 "fileno method returned a non-integer");
Barry Warsawc1cb3601996-12-12 22:16:21 +0000114 Py_DECREF(fno);
115 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000116 }
117 v = PyInt_AsLong(fno);
118 Py_DECREF(fno);
119 }
120 else {
121 PyErr_SetString(PyExc_TypeError,
Barry Warsawc1cb3601996-12-12 22:16:21 +0000122 "argument must be an int, or have a fileno() method.");
123 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000124 }
Guido van Rossum947a0fa2000-01-14 16:33:09 +0000125#if defined(_MSC_VER)
Barry Warsawc1cb3601996-12-12 22:16:21 +0000126 max = 0; /* not used for Win32 */
127#else /* !_MSC_VER */
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000128 if (v < 0 || v >= FD_SETSIZE) {
Barry Warsawc1cb3601996-12-12 22:16:21 +0000129 PyErr_SetString(PyExc_ValueError,
130 "filedescriptor out of range in select()");
131 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000132 }
133 if (v > max)
134 max = v;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000135#endif /* _MSC_VER */
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000136 FD_SET(v, set);
Barry Warsawc1cb3601996-12-12 22:16:21 +0000137
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000138 /* add object and its file descriptor to the list */
139 if (index >= FD_SETSIZE) {
Barry Warsawc1cb3601996-12-12 22:16:21 +0000140 PyErr_SetString(PyExc_ValueError,
141 "too many file descriptors in select()");
142 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000143 }
144 fd2obj[index].obj = o;
145 fd2obj[index].fd = v;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000146 fd2obj[index].sentinel = 0;
147 fd2obj[++index].sentinel = -1;
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000148 }
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000149 return max+1;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000150
151 finally:
152 Py_XDECREF(o);
153 return -1;
Guido van Rossumed233a51992-06-23 09:07:03 +0000154}
155
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000156/* returns NULL and sets the Python exception if an error occurred */
157static PyObject *
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000158set2list(set, fd2obj)
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000159 fd_set *set;
160 pylist fd2obj[FD_SETSIZE + 3];
Guido van Rossumed233a51992-06-23 09:07:03 +0000161{
Barry Warsawc1cb3601996-12-12 22:16:21 +0000162 int i, j, count=0;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000163 PyObject *list, *o;
164 SOCKET fd;
Guido van Rossumed233a51992-06-23 09:07:03 +0000165
Barry Warsawc1cb3601996-12-12 22:16:21 +0000166 for (j = 0; fd2obj[j].sentinel >= 0; j++) {
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000167 if (FD_ISSET(fd2obj[j].fd, set))
Barry Warsawc1cb3601996-12-12 22:16:21 +0000168 count++;
169 }
170 list = PyList_New(count);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000171 if (!list)
172 return NULL;
173
Barry Warsawc1cb3601996-12-12 22:16:21 +0000174 i = 0;
175 for (j = 0; fd2obj[j].sentinel >= 0; j++) {
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000176 fd = fd2obj[j].fd;
177 if (FD_ISSET(fd, set)) {
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000178#ifndef _MSC_VER
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000179 if (fd > FD_SETSIZE) {
180 PyErr_SetString(PyExc_SystemError,
181 "filedescriptor out of range returned in select()");
Barry Warsawc1cb3601996-12-12 22:16:21 +0000182 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000183 }
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000184#endif
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000185 o = fd2obj[j].obj;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000186 fd2obj[j].obj = NULL;
187 /* transfer ownership */
188 if (PyList_SetItem(list, i, o) < 0)
189 goto finally;
190
191 i++;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000192 }
193 }
194 return list;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000195 finally:
196 Py_DECREF(list);
197 return NULL;
Guido van Rossumed233a51992-06-23 09:07:03 +0000198}
Barry Warsawc1cb3601996-12-12 22:16:21 +0000199
Guido van Rossumed233a51992-06-23 09:07:03 +0000200
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000201static PyObject *
Guido van Rossumed233a51992-06-23 09:07:03 +0000202select_select(self, args)
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000203 PyObject *self;
204 PyObject *args;
Guido van Rossumed233a51992-06-23 09:07:03 +0000205{
Guido van Rossumd20781b1998-07-02 02:53:36 +0000206#ifdef MS_WINDOWS
207 /* This would be an awful lot of stack space on Windows! */
208 pylist *rfd2obj, *wfd2obj, *efd2obj;
209#else
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000210 pylist rfd2obj[FD_SETSIZE + 3];
211 pylist wfd2obj[FD_SETSIZE + 3];
212 pylist efd2obj[FD_SETSIZE + 3];
Guido van Rossumd20781b1998-07-02 02:53:36 +0000213#endif
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000214 PyObject *ifdlist, *ofdlist, *efdlist;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000215 PyObject *ret = NULL;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000216 PyObject *tout = Py_None;
217 fd_set ifdset, ofdset, efdset;
218 double timeout;
219 struct timeval tv, *tvp;
Guido van Rossum3262e162000-06-28 21:18:13 +0000220 long seconds;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000221 int imax, omax, emax, max;
222 int n;
Guido van Rossumed233a51992-06-23 09:07:03 +0000223
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000224 /* convert arguments */
Guido van Rossum43713e52000-02-29 13:59:29 +0000225 if (!PyArg_ParseTuple(args, "OOO|O:select",
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000226 &ifdlist, &ofdlist, &efdlist, &tout))
227 return NULL;
Guido van Rossumed233a51992-06-23 09:07:03 +0000228
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000229 if (tout == Py_None)
230 tvp = (struct timeval *)0;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000231 else if (!PyArg_Parse(tout, "d", &timeout)) {
232 PyErr_SetString(PyExc_TypeError,
233 "timeout must be a float or None");
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000234 return NULL;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000235 }
Guido van Rossumc7a22701993-11-01 16:27:16 +0000236 else {
Guido van Rossum3262e162000-06-28 21:18:13 +0000237 if (timeout > (double)LONG_MAX) {
238 PyErr_SetString(PyExc_OverflowError, "timeout period too long");
239 return NULL;
240 }
241 seconds = (long)timeout;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000242 timeout = timeout - (double)seconds;
243 tv.tv_sec = seconds;
Guido van Rossum3262e162000-06-28 21:18:13 +0000244 tv.tv_usec = (long)(timeout*1000000.0);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000245 tvp = &tv;
Guido van Rossumc7a22701993-11-01 16:27:16 +0000246 }
Guido van Rossumed233a51992-06-23 09:07:03 +0000247
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000248 /* sanity check first three arguments */
249 if (!PyList_Check(ifdlist) ||
250 !PyList_Check(ofdlist) ||
251 !PyList_Check(efdlist))
252 {
253 PyErr_SetString(PyExc_TypeError,
254 "arguments 1-3 must be lists");
255 return NULL;
256 }
Guido van Rossumed233a51992-06-23 09:07:03 +0000257
Guido van Rossumd20781b1998-07-02 02:53:36 +0000258#ifdef MS_WINDOWS
259 /* Allocate memory for the lists */
260 rfd2obj = PyMem_NEW(pylist, FD_SETSIZE + 3);
261 wfd2obj = PyMem_NEW(pylist, FD_SETSIZE + 3);
262 efd2obj = PyMem_NEW(pylist, FD_SETSIZE + 3);
263 if (rfd2obj == NULL || wfd2obj == NULL || efd2obj == NULL) {
Guido van Rossumb18618d2000-05-03 23:44:39 +0000264 if (rfd2obj) PyMem_DEL(rfd2obj);
265 if (wfd2obj) PyMem_DEL(wfd2obj);
266 if (efd2obj) PyMem_DEL(efd2obj);
Guido van Rossumd20781b1998-07-02 02:53:36 +0000267 return NULL;
268 }
269#endif
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000270 /* Convert lists to fd_sets, and get maximum fd number
271 * propagates the Python exception set in list2set()
272 */
Barry Warsawc1cb3601996-12-12 22:16:21 +0000273 rfd2obj[0].sentinel = -1;
274 wfd2obj[0].sentinel = -1;
275 efd2obj[0].sentinel = -1;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000276 if ((imax=list2set(ifdlist, &ifdset, rfd2obj)) < 0)
Barry Warsawc1cb3601996-12-12 22:16:21 +0000277 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000278 if ((omax=list2set(ofdlist, &ofdset, wfd2obj)) < 0)
Barry Warsawc1cb3601996-12-12 22:16:21 +0000279 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000280 if ((emax=list2set(efdlist, &efdset, efd2obj)) < 0)
Barry Warsawc1cb3601996-12-12 22:16:21 +0000281 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000282 max = imax;
283 if (omax > max) max = omax;
284 if (emax > max) max = emax;
Guido van Rossumed233a51992-06-23 09:07:03 +0000285
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000286 Py_BEGIN_ALLOW_THREADS
287 n = select(max, &ifdset, &ofdset, &efdset, tvp);
288 Py_END_ALLOW_THREADS
Guido van Rossumed233a51992-06-23 09:07:03 +0000289
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000290 if (n < 0) {
291 PyErr_SetFromErrno(SelectError);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000292 }
Barry Warsawc1cb3601996-12-12 22:16:21 +0000293 else if (n == 0) {
294 /* optimization */
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000295 ifdlist = PyList_New(0);
Barry Warsawc1cb3601996-12-12 22:16:21 +0000296 if (ifdlist) {
297 ret = Py_BuildValue("OOO", ifdlist, ifdlist, ifdlist);
298 Py_DECREF(ifdlist);
299 }
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000300 }
Barry Warsawc1cb3601996-12-12 22:16:21 +0000301 else {
302 /* any of these three calls can raise an exception. it's more
303 convenient to test for this after all three calls... but
304 is that acceptable?
305 */
306 ifdlist = set2list(&ifdset, rfd2obj);
307 ofdlist = set2list(&ofdset, wfd2obj);
308 efdlist = set2list(&efdset, efd2obj);
309 if (PyErr_Occurred())
310 ret = NULL;
311 else
312 ret = Py_BuildValue("OOO", ifdlist, ofdlist, efdlist);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000313
Barry Warsawc1cb3601996-12-12 22:16:21 +0000314 Py_DECREF(ifdlist);
315 Py_DECREF(ofdlist);
316 Py_DECREF(efdlist);
317 }
318
319 finally:
320 reap_obj(rfd2obj);
321 reap_obj(wfd2obj);
322 reap_obj(efd2obj);
Guido van Rossumd20781b1998-07-02 02:53:36 +0000323#ifdef MS_WINDOWS
324 PyMem_DEL(rfd2obj);
325 PyMem_DEL(wfd2obj);
326 PyMem_DEL(efd2obj);
327#endif
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000328 return ret;
Guido van Rossumed233a51992-06-23 09:07:03 +0000329}
330
Guido van Rossum1d8fb2d1998-06-28 16:54:49 +0000331static char select_doc[] =
332"select(rlist, wlist, xlist[, timeout]) -> (rlist, wlist, xlist)\n\
333\n\
334Wait until one or more file descriptors are ready for some kind of I/O.\n\
335The first three arguments are lists of file descriptors to be waited for:\n\
336rlist -- wait until ready for reading\n\
337wlist -- wait until ready for writing\n\
338xlist -- wait for an ``exceptional condition''\n\
339If only one kind of condition is required, pass [] for the other lists.\n\
340A file descriptor is either a socket or file object, or a small integer\n\
341gotten from a fileno() method call on one of those.\n\
342\n\
343The optional 4th argument specifies a timeout in seconds; it may be\n\
344a floating point number to specify fractions of seconds. If it is absent\n\
345or None, the call will never time out.\n\
346\n\
347The return value is a tuple of three lists corresponding to the first three\n\
348arguments; each contains the subset of the corresponding file descriptors\n\
349that are ready.\n\
350\n\
351*** IMPORTANT NOTICE ***\n\
352On Windows, only sockets are supported; on Unix, all file descriptors.";
353
Guido van Rossumed233a51992-06-23 09:07:03 +0000354
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000355static PyMethodDef select_methods[] = {
Guido van Rossum1d8fb2d1998-06-28 16:54:49 +0000356 {"select", select_select, 1, select_doc},
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000357 {0, 0}, /* sentinel */
Guido van Rossumed233a51992-06-23 09:07:03 +0000358};
359
Guido van Rossum1d8fb2d1998-06-28 16:54:49 +0000360static char module_doc[] =
361"This module supports asynchronous I/O on multiple file descriptors.\n\
362\n\
363*** IMPORTANT NOTICE ***\n\
364On Windows, only sockets are supported; on Unix, all file descriptors.";
Guido van Rossumed233a51992-06-23 09:07:03 +0000365
Guido van Rossum3886bb61998-12-04 18:50:17 +0000366DL_EXPORT(void)
Guido van Rossumed233a51992-06-23 09:07:03 +0000367initselect()
368{
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000369 PyObject *m, *d;
Guido van Rossum1d8fb2d1998-06-28 16:54:49 +0000370 m = Py_InitModule3("select", select_methods, module_doc);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000371 d = PyModule_GetDict(m);
Guido van Rossum0cb96de1997-10-01 04:29:29 +0000372 SelectError = PyErr_NewException("select.error", NULL, NULL);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000373 PyDict_SetItemString(d, "error", SelectError);
Guido van Rossumed233a51992-06-23 09:07:03 +0000374}