blob: 7655c3c8b01c5c13ad304ccf5e80531f910f58d4 [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 Rossum6f489d91996-06-28 20:15:15 +000051#ifdef MS_WINDOWS
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000052#include <winsock.h>
53#else
Guido van Rossumb6775db1994-08-01 11:34:53 +000054#include "myselect.h" /* Also includes mytime.h */
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000055#define SOCKET int
56#endif
Guido van Rossumed233a51992-06-23 09:07:03 +000057
Barry Warsawe4ac0aa1996-12-12 00:04:35 +000058static PyObject *SelectError;
Guido van Rossumed233a51992-06-23 09:07:03 +000059
Barry Warsawc1cb3601996-12-12 22:16:21 +000060/* list of Python objects and their file descriptor */
61typedef struct {
62 PyObject *obj; /* owned reference */
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000063 SOCKET fd;
Barry Warsawc1cb3601996-12-12 22:16:21 +000064 int sentinel; /* -1 == sentinel */
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000065} pylist;
66
Barry Warsawc1cb3601996-12-12 22:16:21 +000067static void
68reap_obj(fd2obj)
69 pylist fd2obj[FD_SETSIZE + 3];
70{
71 int i;
72 for (i = 0; i < FD_SETSIZE + 3 && fd2obj[i].sentinel >= 0; i++) {
73 Py_XDECREF(fd2obj[i].obj);
74 fd2obj[i].obj = NULL;
75 }
76 fd2obj[0].sentinel = -1;
77}
78
79
Barry Warsawe4ac0aa1996-12-12 00:04:35 +000080/* returns -1 and sets the Python exception if an error occurred, otherwise
81 returns a number >= 0
82*/
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000083static int
Guido van Rossum4fbf7981992-08-04 09:13:45 +000084list2set(list, set, fd2obj)
Barry Warsawe4ac0aa1996-12-12 00:04:35 +000085 PyObject *list;
86 fd_set *set;
87 pylist fd2obj[FD_SETSIZE + 3];
Guido van Rossumed233a51992-06-23 09:07:03 +000088{
Barry Warsawc1cb3601996-12-12 22:16:21 +000089 int i;
90 int max = -1;
91 int index = 0;
92 int len = PyList_Size(list);
93 PyObject* o = NULL;
Guido van Rossum07432c01995-03-29 16:47:45 +000094
Barry Warsawe4ac0aa1996-12-12 00:04:35 +000095 fd2obj[0].obj = (PyObject*)0; /* set list to zero size */
Barry Warsawe4ac0aa1996-12-12 00:04:35 +000096 FD_ZERO(set);
Barry Warsawc1cb3601996-12-12 22:16:21 +000097
98 for (i = 0; i < len; i++) {
99 PyObject *meth;
100 SOCKET v;
101
102 /* any intervening fileno() calls could decr this refcnt */
Barry Warsaw24c4b3d1996-12-13 23:22:42 +0000103 if (!(o = PyList_GetItem(list, i)))
Barry Warsaw529fcfe1996-12-16 18:15:34 +0000104 return -1;
Barry Warsaw24c4b3d1996-12-13 23:22:42 +0000105
Barry Warsawc1cb3601996-12-12 22:16:21 +0000106 Py_INCREF(o);
107
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000108 if (PyInt_Check(o)) {
109 v = PyInt_AsLong(o);
110 }
111 else if ((meth = PyObject_GetAttrString(o, "fileno")) != NULL)
112 {
Barry Warsawc1cb3601996-12-12 22:16:21 +0000113 PyObject *fno = PyEval_CallObject(meth, NULL);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000114 Py_DECREF(meth);
115 if (fno == NULL)
Barry Warsawc1cb3601996-12-12 22:16:21 +0000116 goto finally;
117
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000118 if (!PyInt_Check(fno)) {
Barry Warsawc1cb3601996-12-12 22:16:21 +0000119 PyErr_SetString(PyExc_TypeError,
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000120 "fileno method returned a non-integer");
Barry Warsawc1cb3601996-12-12 22:16:21 +0000121 Py_DECREF(fno);
122 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000123 }
124 v = PyInt_AsLong(fno);
125 Py_DECREF(fno);
126 }
127 else {
128 PyErr_SetString(PyExc_TypeError,
Barry Warsawc1cb3601996-12-12 22:16:21 +0000129 "argument must be an int, or have a fileno() method.");
130 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000131 }
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000132#ifdef _MSC_VER
Barry Warsawc1cb3601996-12-12 22:16:21 +0000133 max = 0; /* not used for Win32 */
134#else /* !_MSC_VER */
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000135 if (v < 0 || v >= FD_SETSIZE) {
Barry Warsawc1cb3601996-12-12 22:16:21 +0000136 PyErr_SetString(PyExc_ValueError,
137 "filedescriptor out of range in select()");
138 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000139 }
140 if (v > max)
141 max = v;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000142#endif /* _MSC_VER */
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000143 FD_SET(v, set);
Barry Warsawc1cb3601996-12-12 22:16:21 +0000144
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000145 /* add object and its file descriptor to the list */
146 if (index >= FD_SETSIZE) {
Barry Warsawc1cb3601996-12-12 22:16:21 +0000147 PyErr_SetString(PyExc_ValueError,
148 "too many file descriptors in select()");
149 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000150 }
151 fd2obj[index].obj = o;
152 fd2obj[index].fd = v;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000153 fd2obj[index].sentinel = 0;
154 fd2obj[++index].sentinel = -1;
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000155 }
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000156 return max+1;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000157
158 finally:
159 Py_XDECREF(o);
160 return -1;
Guido van Rossumed233a51992-06-23 09:07:03 +0000161}
162
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000163/* returns NULL and sets the Python exception if an error occurred */
164static PyObject *
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000165set2list(set, fd2obj)
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000166 fd_set *set;
167 pylist fd2obj[FD_SETSIZE + 3];
Guido van Rossumed233a51992-06-23 09:07:03 +0000168{
Barry Warsawc1cb3601996-12-12 22:16:21 +0000169 int i, j, count=0;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000170 PyObject *list, *o;
171 SOCKET fd;
Guido van Rossumed233a51992-06-23 09:07:03 +0000172
Barry Warsawc1cb3601996-12-12 22:16:21 +0000173 for (j = 0; fd2obj[j].sentinel >= 0; j++) {
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000174 if (FD_ISSET(fd2obj[j].fd, set))
Barry Warsawc1cb3601996-12-12 22:16:21 +0000175 count++;
176 }
177 list = PyList_New(count);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000178 if (!list)
179 return NULL;
180
Barry Warsawc1cb3601996-12-12 22:16:21 +0000181 i = 0;
182 for (j = 0; fd2obj[j].sentinel >= 0; j++) {
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000183 fd = fd2obj[j].fd;
184 if (FD_ISSET(fd, set)) {
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000185#ifndef _MSC_VER
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000186 if (fd > FD_SETSIZE) {
187 PyErr_SetString(PyExc_SystemError,
188 "filedescriptor out of range returned in select()");
Barry Warsawc1cb3601996-12-12 22:16:21 +0000189 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000190 }
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000191#endif
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000192 o = fd2obj[j].obj;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000193 fd2obj[j].obj = NULL;
194 /* transfer ownership */
195 if (PyList_SetItem(list, i, o) < 0)
196 goto finally;
197
198 i++;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000199 }
200 }
201 return list;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000202 finally:
203 Py_DECREF(list);
204 return NULL;
Guido van Rossumed233a51992-06-23 09:07:03 +0000205}
Barry Warsawc1cb3601996-12-12 22:16:21 +0000206
Guido van Rossumed233a51992-06-23 09:07:03 +0000207
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000208static PyObject *
Guido van Rossumed233a51992-06-23 09:07:03 +0000209select_select(self, args)
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000210 PyObject *self;
211 PyObject *args;
Guido van Rossumed233a51992-06-23 09:07:03 +0000212{
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000213 pylist rfd2obj[FD_SETSIZE + 3];
214 pylist wfd2obj[FD_SETSIZE + 3];
215 pylist efd2obj[FD_SETSIZE + 3];
216 PyObject *ifdlist, *ofdlist, *efdlist;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000217 PyObject *ret = NULL;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000218 PyObject *tout = Py_None;
219 fd_set ifdset, ofdset, efdset;
220 double timeout;
221 struct timeval tv, *tvp;
222 int seconds;
223 int imax, omax, emax, max;
224 int n;
Guido van Rossumed233a51992-06-23 09:07:03 +0000225
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000226 /* convert arguments */
227 if (!PyArg_ParseTuple(args, "OOO|O",
228 &ifdlist, &ofdlist, &efdlist, &tout))
229 return NULL;
Guido van Rossumed233a51992-06-23 09:07:03 +0000230
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000231 if (tout == Py_None)
232 tvp = (struct timeval *)0;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000233 else if (!PyArg_Parse(tout, "d", &timeout)) {
234 PyErr_SetString(PyExc_TypeError,
235 "timeout must be a float or None");
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000236 return NULL;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000237 }
Guido van Rossumc7a22701993-11-01 16:27:16 +0000238 else {
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000239 seconds = (int)timeout;
240 timeout = timeout - (double)seconds;
241 tv.tv_sec = seconds;
242 tv.tv_usec = (int)(timeout*1000000.0);
243 tvp = &tv;
Guido van Rossumc7a22701993-11-01 16:27:16 +0000244 }
Guido van Rossumed233a51992-06-23 09:07:03 +0000245
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000246 /* sanity check first three arguments */
247 if (!PyList_Check(ifdlist) ||
248 !PyList_Check(ofdlist) ||
249 !PyList_Check(efdlist))
250 {
251 PyErr_SetString(PyExc_TypeError,
252 "arguments 1-3 must be lists");
253 return NULL;
254 }
Guido van Rossumed233a51992-06-23 09:07:03 +0000255
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000256 /* Convert lists to fd_sets, and get maximum fd number
257 * propagates the Python exception set in list2set()
258 */
Barry Warsawc1cb3601996-12-12 22:16:21 +0000259 rfd2obj[0].sentinel = -1;
260 wfd2obj[0].sentinel = -1;
261 efd2obj[0].sentinel = -1;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000262 if ((imax=list2set(ifdlist, &ifdset, rfd2obj)) < 0)
Barry Warsawc1cb3601996-12-12 22:16:21 +0000263 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000264 if ((omax=list2set(ofdlist, &ofdset, wfd2obj)) < 0)
Barry Warsawc1cb3601996-12-12 22:16:21 +0000265 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000266 if ((emax=list2set(efdlist, &efdset, efd2obj)) < 0)
Barry Warsawc1cb3601996-12-12 22:16:21 +0000267 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000268 max = imax;
269 if (omax > max) max = omax;
270 if (emax > max) max = emax;
Guido van Rossumed233a51992-06-23 09:07:03 +0000271
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000272 Py_BEGIN_ALLOW_THREADS
273 n = select(max, &ifdset, &ofdset, &efdset, tvp);
274 Py_END_ALLOW_THREADS
Guido van Rossumed233a51992-06-23 09:07:03 +0000275
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000276 if (n < 0) {
277 PyErr_SetFromErrno(SelectError);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000278 }
Barry Warsawc1cb3601996-12-12 22:16:21 +0000279 else if (n == 0) {
280 /* optimization */
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000281 ifdlist = PyList_New(0);
Barry Warsawc1cb3601996-12-12 22:16:21 +0000282 if (ifdlist) {
283 ret = Py_BuildValue("OOO", ifdlist, ifdlist, ifdlist);
284 Py_DECREF(ifdlist);
285 }
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000286 }
Barry Warsawc1cb3601996-12-12 22:16:21 +0000287 else {
288 /* any of these three calls can raise an exception. it's more
289 convenient to test for this after all three calls... but
290 is that acceptable?
291 */
292 ifdlist = set2list(&ifdset, rfd2obj);
293 ofdlist = set2list(&ofdset, wfd2obj);
294 efdlist = set2list(&efdset, efd2obj);
295 if (PyErr_Occurred())
296 ret = NULL;
297 else
298 ret = Py_BuildValue("OOO", ifdlist, ofdlist, efdlist);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000299
Barry Warsawc1cb3601996-12-12 22:16:21 +0000300 Py_DECREF(ifdlist);
301 Py_DECREF(ofdlist);
302 Py_DECREF(efdlist);
303 }
304
305 finally:
306 reap_obj(rfd2obj);
307 reap_obj(wfd2obj);
308 reap_obj(efd2obj);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000309 return ret;
Guido van Rossumed233a51992-06-23 09:07:03 +0000310}
311
312
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000313static PyMethodDef select_methods[] = {
314 {"select", select_select, 1},
315 {0, 0}, /* sentinel */
Guido van Rossumed233a51992-06-23 09:07:03 +0000316};
317
318
319void
320initselect()
321{
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000322 PyObject *m, *d;
323 m = Py_InitModule("select", select_methods);
324 d = PyModule_GetDict(m);
Guido van Rossum0cb96de1997-10-01 04:29:29 +0000325 SelectError = PyErr_NewException("select.error", NULL, NULL);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000326 PyDict_SetItemString(d, "error", SelectError);
Guido van Rossumed233a51992-06-23 09:07:03 +0000327}