blob: 391318199c005e7ca974e8521a0d569e2f50db8c [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 Rossum4f0fbf81996-06-12 04:22:53 +000036*/
Guido van Rossumed233a51992-06-23 09:07:03 +000037
Barry Warsawe4ac0aa1996-12-12 00:04:35 +000038#include "Python.h"
Guido van Rossumed233a51992-06-23 09:07:03 +000039
Guido van Rossuma376cc51996-12-05 23:43:35 +000040#ifdef HAVE_UNISTD_H
41#include <unistd.h>
42#endif
43
Guido van Rossum37273171996-12-09 18:47:43 +000044#ifdef __sgi
45/* This is missing from unistd.h */
46extern void bzero();
47#endif
48
Guido van Rossumb6775db1994-08-01 11:34:53 +000049#include <sys/types.h>
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000050
Guido van Rossum8e9ebfd1997-11-22 21:53:48 +000051#if defined(PYOS_OS2)
52#include <sys/time.h>
53#include <utils.h>
54#endif
55
Guido van Rossum6f489d91996-06-28 20:15:15 +000056#ifdef MS_WINDOWS
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000057#include <winsock.h>
58#else
Guido van Rossumb6775db1994-08-01 11:34:53 +000059#include "myselect.h" /* Also includes mytime.h */
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000060#define SOCKET int
61#endif
Guido van Rossumed233a51992-06-23 09:07:03 +000062
Barry Warsawe4ac0aa1996-12-12 00:04:35 +000063static PyObject *SelectError;
Guido van Rossumed233a51992-06-23 09:07:03 +000064
Barry Warsawc1cb3601996-12-12 22:16:21 +000065/* list of Python objects and their file descriptor */
66typedef struct {
67 PyObject *obj; /* owned reference */
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000068 SOCKET fd;
Barry Warsawc1cb3601996-12-12 22:16:21 +000069 int sentinel; /* -1 == sentinel */
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000070} pylist;
71
Barry Warsawc1cb3601996-12-12 22:16:21 +000072static void
73reap_obj(fd2obj)
74 pylist fd2obj[FD_SETSIZE + 3];
75{
76 int i;
77 for (i = 0; i < FD_SETSIZE + 3 && fd2obj[i].sentinel >= 0; i++) {
78 Py_XDECREF(fd2obj[i].obj);
79 fd2obj[i].obj = NULL;
80 }
81 fd2obj[0].sentinel = -1;
82}
83
84
Barry Warsawe4ac0aa1996-12-12 00:04:35 +000085/* returns -1 and sets the Python exception if an error occurred, otherwise
86 returns a number >= 0
87*/
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000088static int
Guido van Rossum4fbf7981992-08-04 09:13:45 +000089list2set(list, set, fd2obj)
Barry Warsawe4ac0aa1996-12-12 00:04:35 +000090 PyObject *list;
91 fd_set *set;
92 pylist fd2obj[FD_SETSIZE + 3];
Guido van Rossumed233a51992-06-23 09:07:03 +000093{
Barry Warsawc1cb3601996-12-12 22:16:21 +000094 int i;
95 int max = -1;
96 int index = 0;
97 int len = PyList_Size(list);
98 PyObject* o = NULL;
Guido van Rossum07432c01995-03-29 16:47:45 +000099
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000100 fd2obj[0].obj = (PyObject*)0; /* set list to zero size */
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000101 FD_ZERO(set);
Barry Warsawc1cb3601996-12-12 22:16:21 +0000102
103 for (i = 0; i < len; i++) {
104 PyObject *meth;
105 SOCKET v;
106
107 /* any intervening fileno() calls could decr this refcnt */
Barry Warsaw24c4b3d1996-12-13 23:22:42 +0000108 if (!(o = PyList_GetItem(list, i)))
Barry Warsaw529fcfe1996-12-16 18:15:34 +0000109 return -1;
Barry Warsaw24c4b3d1996-12-13 23:22:42 +0000110
Barry Warsawc1cb3601996-12-12 22:16:21 +0000111 Py_INCREF(o);
112
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000113 if (PyInt_Check(o)) {
114 v = PyInt_AsLong(o);
115 }
116 else if ((meth = PyObject_GetAttrString(o, "fileno")) != NULL)
117 {
Barry Warsawc1cb3601996-12-12 22:16:21 +0000118 PyObject *fno = PyEval_CallObject(meth, NULL);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000119 Py_DECREF(meth);
120 if (fno == NULL)
Barry Warsawc1cb3601996-12-12 22:16:21 +0000121 goto finally;
122
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000123 if (!PyInt_Check(fno)) {
Barry Warsawc1cb3601996-12-12 22:16:21 +0000124 PyErr_SetString(PyExc_TypeError,
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000125 "fileno method returned a non-integer");
Barry Warsawc1cb3601996-12-12 22:16:21 +0000126 Py_DECREF(fno);
127 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000128 }
129 v = PyInt_AsLong(fno);
130 Py_DECREF(fno);
131 }
132 else {
133 PyErr_SetString(PyExc_TypeError,
Barry Warsawc1cb3601996-12-12 22:16:21 +0000134 "argument must be an int, or have a fileno() method.");
135 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000136 }
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000137#ifdef _MSC_VER
Barry Warsawc1cb3601996-12-12 22:16:21 +0000138 max = 0; /* not used for Win32 */
139#else /* !_MSC_VER */
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000140 if (v < 0 || v >= FD_SETSIZE) {
Barry Warsawc1cb3601996-12-12 22:16:21 +0000141 PyErr_SetString(PyExc_ValueError,
142 "filedescriptor out of range in select()");
143 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000144 }
145 if (v > max)
146 max = v;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000147#endif /* _MSC_VER */
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000148 FD_SET(v, set);
Barry Warsawc1cb3601996-12-12 22:16:21 +0000149
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000150 /* add object and its file descriptor to the list */
151 if (index >= FD_SETSIZE) {
Barry Warsawc1cb3601996-12-12 22:16:21 +0000152 PyErr_SetString(PyExc_ValueError,
153 "too many file descriptors in select()");
154 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000155 }
156 fd2obj[index].obj = o;
157 fd2obj[index].fd = v;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000158 fd2obj[index].sentinel = 0;
159 fd2obj[++index].sentinel = -1;
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000160 }
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000161 return max+1;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000162
163 finally:
164 Py_XDECREF(o);
165 return -1;
Guido van Rossumed233a51992-06-23 09:07:03 +0000166}
167
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000168/* returns NULL and sets the Python exception if an error occurred */
169static PyObject *
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000170set2list(set, fd2obj)
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000171 fd_set *set;
172 pylist fd2obj[FD_SETSIZE + 3];
Guido van Rossumed233a51992-06-23 09:07:03 +0000173{
Barry Warsawc1cb3601996-12-12 22:16:21 +0000174 int i, j, count=0;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000175 PyObject *list, *o;
176 SOCKET fd;
Guido van Rossumed233a51992-06-23 09:07:03 +0000177
Barry Warsawc1cb3601996-12-12 22:16:21 +0000178 for (j = 0; fd2obj[j].sentinel >= 0; j++) {
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000179 if (FD_ISSET(fd2obj[j].fd, set))
Barry Warsawc1cb3601996-12-12 22:16:21 +0000180 count++;
181 }
182 list = PyList_New(count);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000183 if (!list)
184 return NULL;
185
Barry Warsawc1cb3601996-12-12 22:16:21 +0000186 i = 0;
187 for (j = 0; fd2obj[j].sentinel >= 0; j++) {
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000188 fd = fd2obj[j].fd;
189 if (FD_ISSET(fd, set)) {
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000190#ifndef _MSC_VER
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000191 if (fd > FD_SETSIZE) {
192 PyErr_SetString(PyExc_SystemError,
193 "filedescriptor out of range returned in select()");
Barry Warsawc1cb3601996-12-12 22:16:21 +0000194 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000195 }
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000196#endif
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000197 o = fd2obj[j].obj;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000198 fd2obj[j].obj = NULL;
199 /* transfer ownership */
200 if (PyList_SetItem(list, i, o) < 0)
201 goto finally;
202
203 i++;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000204 }
205 }
206 return list;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000207 finally:
208 Py_DECREF(list);
209 return NULL;
Guido van Rossumed233a51992-06-23 09:07:03 +0000210}
Barry Warsawc1cb3601996-12-12 22:16:21 +0000211
Guido van Rossumed233a51992-06-23 09:07:03 +0000212
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000213static PyObject *
Guido van Rossumed233a51992-06-23 09:07:03 +0000214select_select(self, args)
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000215 PyObject *self;
216 PyObject *args;
Guido van Rossumed233a51992-06-23 09:07:03 +0000217{
Guido van Rossumd20781b1998-07-02 02:53:36 +0000218#ifdef MS_WINDOWS
219 /* This would be an awful lot of stack space on Windows! */
220 pylist *rfd2obj, *wfd2obj, *efd2obj;
221#else
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000222 pylist rfd2obj[FD_SETSIZE + 3];
223 pylist wfd2obj[FD_SETSIZE + 3];
224 pylist efd2obj[FD_SETSIZE + 3];
Guido van Rossumd20781b1998-07-02 02:53:36 +0000225#endif
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000226 PyObject *ifdlist, *ofdlist, *efdlist;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000227 PyObject *ret = NULL;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000228 PyObject *tout = Py_None;
229 fd_set ifdset, ofdset, efdset;
230 double timeout;
231 struct timeval tv, *tvp;
232 int seconds;
233 int imax, omax, emax, max;
234 int n;
Guido van Rossumed233a51992-06-23 09:07:03 +0000235
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000236 /* convert arguments */
237 if (!PyArg_ParseTuple(args, "OOO|O",
238 &ifdlist, &ofdlist, &efdlist, &tout))
239 return NULL;
Guido van Rossumed233a51992-06-23 09:07:03 +0000240
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000241 if (tout == Py_None)
242 tvp = (struct timeval *)0;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000243 else if (!PyArg_Parse(tout, "d", &timeout)) {
244 PyErr_SetString(PyExc_TypeError,
245 "timeout must be a float or None");
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000246 return NULL;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000247 }
Guido van Rossumc7a22701993-11-01 16:27:16 +0000248 else {
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000249 seconds = (int)timeout;
250 timeout = timeout - (double)seconds;
251 tv.tv_sec = seconds;
252 tv.tv_usec = (int)(timeout*1000000.0);
253 tvp = &tv;
Guido van Rossumc7a22701993-11-01 16:27:16 +0000254 }
Guido van Rossumed233a51992-06-23 09:07:03 +0000255
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000256 /* sanity check first three arguments */
257 if (!PyList_Check(ifdlist) ||
258 !PyList_Check(ofdlist) ||
259 !PyList_Check(efdlist))
260 {
261 PyErr_SetString(PyExc_TypeError,
262 "arguments 1-3 must be lists");
263 return NULL;
264 }
Guido van Rossumed233a51992-06-23 09:07:03 +0000265
Guido van Rossumd20781b1998-07-02 02:53:36 +0000266#ifdef MS_WINDOWS
267 /* Allocate memory for the lists */
268 rfd2obj = PyMem_NEW(pylist, FD_SETSIZE + 3);
269 wfd2obj = PyMem_NEW(pylist, FD_SETSIZE + 3);
270 efd2obj = PyMem_NEW(pylist, FD_SETSIZE + 3);
271 if (rfd2obj == NULL || wfd2obj == NULL || efd2obj == NULL) {
272 PyMem_XDEL(rfd2obj);
273 PyMem_XDEL(wfd2obj);
274 PyMem_XDEL(efd2obj);
275 return NULL;
276 }
277#endif
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000278 /* Convert lists to fd_sets, and get maximum fd number
279 * propagates the Python exception set in list2set()
280 */
Barry Warsawc1cb3601996-12-12 22:16:21 +0000281 rfd2obj[0].sentinel = -1;
282 wfd2obj[0].sentinel = -1;
283 efd2obj[0].sentinel = -1;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000284 if ((imax=list2set(ifdlist, &ifdset, rfd2obj)) < 0)
Barry Warsawc1cb3601996-12-12 22:16:21 +0000285 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000286 if ((omax=list2set(ofdlist, &ofdset, wfd2obj)) < 0)
Barry Warsawc1cb3601996-12-12 22:16:21 +0000287 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000288 if ((emax=list2set(efdlist, &efdset, efd2obj)) < 0)
Barry Warsawc1cb3601996-12-12 22:16:21 +0000289 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000290 max = imax;
291 if (omax > max) max = omax;
292 if (emax > max) max = emax;
Guido van Rossumed233a51992-06-23 09:07:03 +0000293
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000294 Py_BEGIN_ALLOW_THREADS
295 n = select(max, &ifdset, &ofdset, &efdset, tvp);
296 Py_END_ALLOW_THREADS
Guido van Rossumed233a51992-06-23 09:07:03 +0000297
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000298 if (n < 0) {
299 PyErr_SetFromErrno(SelectError);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000300 }
Barry Warsawc1cb3601996-12-12 22:16:21 +0000301 else if (n == 0) {
302 /* optimization */
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000303 ifdlist = PyList_New(0);
Barry Warsawc1cb3601996-12-12 22:16:21 +0000304 if (ifdlist) {
305 ret = Py_BuildValue("OOO", ifdlist, ifdlist, ifdlist);
306 Py_DECREF(ifdlist);
307 }
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000308 }
Barry Warsawc1cb3601996-12-12 22:16:21 +0000309 else {
310 /* any of these three calls can raise an exception. it's more
311 convenient to test for this after all three calls... but
312 is that acceptable?
313 */
314 ifdlist = set2list(&ifdset, rfd2obj);
315 ofdlist = set2list(&ofdset, wfd2obj);
316 efdlist = set2list(&efdset, efd2obj);
317 if (PyErr_Occurred())
318 ret = NULL;
319 else
320 ret = Py_BuildValue("OOO", ifdlist, ofdlist, efdlist);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000321
Barry Warsawc1cb3601996-12-12 22:16:21 +0000322 Py_DECREF(ifdlist);
323 Py_DECREF(ofdlist);
324 Py_DECREF(efdlist);
325 }
326
327 finally:
328 reap_obj(rfd2obj);
329 reap_obj(wfd2obj);
330 reap_obj(efd2obj);
Guido van Rossumd20781b1998-07-02 02:53:36 +0000331#ifdef MS_WINDOWS
332 PyMem_DEL(rfd2obj);
333 PyMem_DEL(wfd2obj);
334 PyMem_DEL(efd2obj);
335#endif
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000336 return ret;
Guido van Rossumed233a51992-06-23 09:07:03 +0000337}
338
Guido van Rossum1d8fb2d1998-06-28 16:54:49 +0000339static char select_doc[] =
340"select(rlist, wlist, xlist[, timeout]) -> (rlist, wlist, xlist)\n\
341\n\
342Wait until one or more file descriptors are ready for some kind of I/O.\n\
343The first three arguments are lists of file descriptors to be waited for:\n\
344rlist -- wait until ready for reading\n\
345wlist -- wait until ready for writing\n\
346xlist -- wait for an ``exceptional condition''\n\
347If only one kind of condition is required, pass [] for the other lists.\n\
348A file descriptor is either a socket or file object, or a small integer\n\
349gotten from a fileno() method call on one of those.\n\
350\n\
351The optional 4th argument specifies a timeout in seconds; it may be\n\
352a floating point number to specify fractions of seconds. If it is absent\n\
353or None, the call will never time out.\n\
354\n\
355The return value is a tuple of three lists corresponding to the first three\n\
356arguments; each contains the subset of the corresponding file descriptors\n\
357that are ready.\n\
358\n\
359*** IMPORTANT NOTICE ***\n\
360On Windows, only sockets are supported; on Unix, all file descriptors.";
361
Guido van Rossumed233a51992-06-23 09:07:03 +0000362
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000363static PyMethodDef select_methods[] = {
Guido van Rossum1d8fb2d1998-06-28 16:54:49 +0000364 {"select", select_select, 1, select_doc},
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000365 {0, 0}, /* sentinel */
Guido van Rossumed233a51992-06-23 09:07:03 +0000366};
367
Guido van Rossum1d8fb2d1998-06-28 16:54:49 +0000368static char module_doc[] =
369"This module supports asynchronous I/O on multiple file descriptors.\n\
370\n\
371*** IMPORTANT NOTICE ***\n\
372On Windows, only sockets are supported; on Unix, all file descriptors.";
Guido van Rossumed233a51992-06-23 09:07:03 +0000373
374void
375initselect()
376{
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000377 PyObject *m, *d;
Guido van Rossum1d8fb2d1998-06-28 16:54:49 +0000378 m = Py_InitModule3("select", select_methods, module_doc);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000379 d = PyModule_GetDict(m);
Guido van Rossum0cb96de1997-10-01 04:29:29 +0000380 SelectError = PyErr_NewException("select.error", NULL, NULL);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000381 PyDict_SetItemString(d, "error", SelectError);
Guido van Rossumed233a51992-06-23 09:07:03 +0000382}