blob: be0c6048c26cb6f4e915ac5dd088bb0876f4878a [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{
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000218 pylist rfd2obj[FD_SETSIZE + 3];
219 pylist wfd2obj[FD_SETSIZE + 3];
220 pylist efd2obj[FD_SETSIZE + 3];
221 PyObject *ifdlist, *ofdlist, *efdlist;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000222 PyObject *ret = NULL;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000223 PyObject *tout = Py_None;
224 fd_set ifdset, ofdset, efdset;
225 double timeout;
226 struct timeval tv, *tvp;
227 int seconds;
228 int imax, omax, emax, max;
229 int n;
Guido van Rossumed233a51992-06-23 09:07:03 +0000230
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000231 /* convert arguments */
232 if (!PyArg_ParseTuple(args, "OOO|O",
233 &ifdlist, &ofdlist, &efdlist, &tout))
234 return NULL;
Guido van Rossumed233a51992-06-23 09:07:03 +0000235
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000236 if (tout == Py_None)
237 tvp = (struct timeval *)0;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000238 else if (!PyArg_Parse(tout, "d", &timeout)) {
239 PyErr_SetString(PyExc_TypeError,
240 "timeout must be a float or None");
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000241 return NULL;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000242 }
Guido van Rossumc7a22701993-11-01 16:27:16 +0000243 else {
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000244 seconds = (int)timeout;
245 timeout = timeout - (double)seconds;
246 tv.tv_sec = seconds;
247 tv.tv_usec = (int)(timeout*1000000.0);
248 tvp = &tv;
Guido van Rossumc7a22701993-11-01 16:27:16 +0000249 }
Guido van Rossumed233a51992-06-23 09:07:03 +0000250
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000251 /* sanity check first three arguments */
252 if (!PyList_Check(ifdlist) ||
253 !PyList_Check(ofdlist) ||
254 !PyList_Check(efdlist))
255 {
256 PyErr_SetString(PyExc_TypeError,
257 "arguments 1-3 must be lists");
258 return NULL;
259 }
Guido van Rossumed233a51992-06-23 09:07:03 +0000260
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000261 /* Convert lists to fd_sets, and get maximum fd number
262 * propagates the Python exception set in list2set()
263 */
Barry Warsawc1cb3601996-12-12 22:16:21 +0000264 rfd2obj[0].sentinel = -1;
265 wfd2obj[0].sentinel = -1;
266 efd2obj[0].sentinel = -1;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000267 if ((imax=list2set(ifdlist, &ifdset, rfd2obj)) < 0)
Barry Warsawc1cb3601996-12-12 22:16:21 +0000268 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000269 if ((omax=list2set(ofdlist, &ofdset, wfd2obj)) < 0)
Barry Warsawc1cb3601996-12-12 22:16:21 +0000270 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000271 if ((emax=list2set(efdlist, &efdset, efd2obj)) < 0)
Barry Warsawc1cb3601996-12-12 22:16:21 +0000272 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000273 max = imax;
274 if (omax > max) max = omax;
275 if (emax > max) max = emax;
Guido van Rossumed233a51992-06-23 09:07:03 +0000276
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000277 Py_BEGIN_ALLOW_THREADS
278 n = select(max, &ifdset, &ofdset, &efdset, tvp);
279 Py_END_ALLOW_THREADS
Guido van Rossumed233a51992-06-23 09:07:03 +0000280
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000281 if (n < 0) {
282 PyErr_SetFromErrno(SelectError);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000283 }
Barry Warsawc1cb3601996-12-12 22:16:21 +0000284 else if (n == 0) {
285 /* optimization */
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000286 ifdlist = PyList_New(0);
Barry Warsawc1cb3601996-12-12 22:16:21 +0000287 if (ifdlist) {
288 ret = Py_BuildValue("OOO", ifdlist, ifdlist, ifdlist);
289 Py_DECREF(ifdlist);
290 }
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000291 }
Barry Warsawc1cb3601996-12-12 22:16:21 +0000292 else {
293 /* any of these three calls can raise an exception. it's more
294 convenient to test for this after all three calls... but
295 is that acceptable?
296 */
297 ifdlist = set2list(&ifdset, rfd2obj);
298 ofdlist = set2list(&ofdset, wfd2obj);
299 efdlist = set2list(&efdset, efd2obj);
300 if (PyErr_Occurred())
301 ret = NULL;
302 else
303 ret = Py_BuildValue("OOO", ifdlist, ofdlist, efdlist);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000304
Barry Warsawc1cb3601996-12-12 22:16:21 +0000305 Py_DECREF(ifdlist);
306 Py_DECREF(ofdlist);
307 Py_DECREF(efdlist);
308 }
309
310 finally:
311 reap_obj(rfd2obj);
312 reap_obj(wfd2obj);
313 reap_obj(efd2obj);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000314 return ret;
Guido van Rossumed233a51992-06-23 09:07:03 +0000315}
316
317
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000318static PyMethodDef select_methods[] = {
319 {"select", select_select, 1},
320 {0, 0}, /* sentinel */
Guido van Rossumed233a51992-06-23 09:07:03 +0000321};
322
323
324void
325initselect()
326{
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000327 PyObject *m, *d;
328 m = Py_InitModule("select", select_methods);
329 d = PyModule_GetDict(m);
Guido van Rossum0cb96de1997-10-01 04:29:29 +0000330 SelectError = PyErr_NewException("select.error", NULL, NULL);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000331 PyDict_SetItemString(d, "error", SelectError);
Guido van Rossumed233a51992-06-23 09:07:03 +0000332}