blob: 2860f3758844bb3d42d254a548e75dccff198679 [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
Jack Jansene4b48632000-07-11 21:35:02 +000024#ifdef HAVE_LIMITS_H
25#include <limits.h>
26#endif
Guido van Rossuma376cc51996-12-05 23:43:35 +000027
Guido van Rossum37273171996-12-09 18:47:43 +000028#ifdef __sgi
29/* This is missing from unistd.h */
Thomas Woutersbd4bc4e2000-07-22 23:57:55 +000030extern void bzero(void *, int);
Guido van Rossum37273171996-12-09 18:47:43 +000031#endif
32
Guido van Rossumff7e83d1999-08-27 20:39:37 +000033#ifndef DONT_HAVE_SYS_TYPES_H
Guido van Rossumb6775db1994-08-01 11:34:53 +000034#include <sys/types.h>
Guido van Rossumff7e83d1999-08-27 20:39:37 +000035#endif
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000036
Guido van Rossum8e9ebfd1997-11-22 21:53:48 +000037#if defined(PYOS_OS2)
38#include <sys/time.h>
39#include <utils.h>
40#endif
41
Guido van Rossum6f489d91996-06-28 20:15:15 +000042#ifdef MS_WINDOWS
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000043#include <winsock.h>
44#else
Guido van Rossumbcc20741998-08-04 22:53:56 +000045#ifdef __BEOS__
46#include <net/socket.h>
47#define SOCKET int
48#else
Guido van Rossumb6775db1994-08-01 11:34:53 +000049#include "myselect.h" /* Also includes mytime.h */
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000050#define SOCKET int
51#endif
Guido van Rossumbcc20741998-08-04 22:53:56 +000052#endif
Guido van Rossumed233a51992-06-23 09:07:03 +000053
Barry Warsawe4ac0aa1996-12-12 00:04:35 +000054static PyObject *SelectError;
Guido van Rossumed233a51992-06-23 09:07:03 +000055
Barry Warsawc1cb3601996-12-12 22:16:21 +000056/* list of Python objects and their file descriptor */
57typedef struct {
58 PyObject *obj; /* owned reference */
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000059 SOCKET fd;
Barry Warsawc1cb3601996-12-12 22:16:21 +000060 int sentinel; /* -1 == sentinel */
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000061} pylist;
62
Barry Warsawc1cb3601996-12-12 22:16:21 +000063static void
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +000064reap_obj(pylist fd2obj[FD_SETSIZE + 3])
Barry Warsawc1cb3601996-12-12 22:16:21 +000065{
66 int i;
67 for (i = 0; i < FD_SETSIZE + 3 && fd2obj[i].sentinel >= 0; i++) {
68 Py_XDECREF(fd2obj[i].obj);
69 fd2obj[i].obj = NULL;
70 }
71 fd2obj[0].sentinel = -1;
72}
73
74
Barry Warsawe4ac0aa1996-12-12 00:04:35 +000075/* returns -1 and sets the Python exception if an error occurred, otherwise
76 returns a number >= 0
77*/
Guido van Rossum4f0fbf81996-06-12 04:22:53 +000078static int
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +000079list2set(PyObject *list, fd_set *set, pylist fd2obj[FD_SETSIZE + 3])
Guido van Rossumed233a51992-06-23 09:07:03 +000080{
Barry Warsawc1cb3601996-12-12 22:16:21 +000081 int i;
82 int max = -1;
83 int index = 0;
84 int len = PyList_Size(list);
85 PyObject* o = NULL;
Guido van Rossum07432c01995-03-29 16:47:45 +000086
Barry Warsawe4ac0aa1996-12-12 00:04:35 +000087 fd2obj[0].obj = (PyObject*)0; /* set list to zero size */
Barry Warsawe4ac0aa1996-12-12 00:04:35 +000088 FD_ZERO(set);
Barry Warsawc1cb3601996-12-12 22:16:21 +000089
90 for (i = 0; i < len; i++) {
Barry Warsawc1cb3601996-12-12 22:16:21 +000091 SOCKET v;
92
93 /* any intervening fileno() calls could decr this refcnt */
Barry Warsaw24c4b3d1996-12-13 23:22:42 +000094 if (!(o = PyList_GetItem(list, i)))
Barry Warsaw529fcfe1996-12-16 18:15:34 +000095 return -1;
Barry Warsaw24c4b3d1996-12-13 23:22:42 +000096
Barry Warsawc1cb3601996-12-12 22:16:21 +000097 Py_INCREF(o);
Andrew M. Kuchling9f28a032000-07-13 23:59:35 +000098 v = PyObject_AsFileDescriptor( o );
99 if (v == -1) goto finally;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000100
Guido van Rossum947a0fa2000-01-14 16:33:09 +0000101#if defined(_MSC_VER)
Barry Warsawc1cb3601996-12-12 22:16:21 +0000102 max = 0; /* not used for Win32 */
103#else /* !_MSC_VER */
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000104 if (v < 0 || v >= FD_SETSIZE) {
Barry Warsawc1cb3601996-12-12 22:16:21 +0000105 PyErr_SetString(PyExc_ValueError,
106 "filedescriptor out of range in select()");
107 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000108 }
109 if (v > max)
110 max = v;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000111#endif /* _MSC_VER */
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000112 FD_SET(v, set);
Barry Warsawc1cb3601996-12-12 22:16:21 +0000113
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000114 /* add object and its file descriptor to the list */
115 if (index >= FD_SETSIZE) {
Barry Warsawc1cb3601996-12-12 22:16:21 +0000116 PyErr_SetString(PyExc_ValueError,
117 "too many file descriptors in select()");
118 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000119 }
120 fd2obj[index].obj = o;
121 fd2obj[index].fd = v;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000122 fd2obj[index].sentinel = 0;
123 fd2obj[++index].sentinel = -1;
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000124 }
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000125 return max+1;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000126
127 finally:
128 Py_XDECREF(o);
129 return -1;
Guido van Rossumed233a51992-06-23 09:07:03 +0000130}
131
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000132/* returns NULL and sets the Python exception if an error occurred */
133static PyObject *
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000134set2list(fd_set *set, pylist fd2obj[FD_SETSIZE + 3])
Guido van Rossumed233a51992-06-23 09:07:03 +0000135{
Barry Warsawc1cb3601996-12-12 22:16:21 +0000136 int i, j, count=0;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000137 PyObject *list, *o;
138 SOCKET fd;
Guido van Rossumed233a51992-06-23 09:07:03 +0000139
Barry Warsawc1cb3601996-12-12 22:16:21 +0000140 for (j = 0; fd2obj[j].sentinel >= 0; j++) {
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000141 if (FD_ISSET(fd2obj[j].fd, set))
Barry Warsawc1cb3601996-12-12 22:16:21 +0000142 count++;
143 }
144 list = PyList_New(count);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000145 if (!list)
146 return NULL;
147
Barry Warsawc1cb3601996-12-12 22:16:21 +0000148 i = 0;
149 for (j = 0; fd2obj[j].sentinel >= 0; j++) {
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000150 fd = fd2obj[j].fd;
151 if (FD_ISSET(fd, set)) {
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000152#ifndef _MSC_VER
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000153 if (fd > FD_SETSIZE) {
154 PyErr_SetString(PyExc_SystemError,
155 "filedescriptor out of range returned in select()");
Barry Warsawc1cb3601996-12-12 22:16:21 +0000156 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000157 }
Guido van Rossum4f0fbf81996-06-12 04:22:53 +0000158#endif
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000159 o = fd2obj[j].obj;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000160 fd2obj[j].obj = NULL;
161 /* transfer ownership */
162 if (PyList_SetItem(list, i, o) < 0)
163 goto finally;
164
165 i++;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000166 }
167 }
168 return list;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000169 finally:
170 Py_DECREF(list);
171 return NULL;
Guido van Rossumed233a51992-06-23 09:07:03 +0000172}
Barry Warsawc1cb3601996-12-12 22:16:21 +0000173
Guido van Rossumed233a51992-06-23 09:07:03 +0000174
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000175static PyObject *
Peter Schneider-Kamp41c36ff2000-07-10 12:29:26 +0000176select_select(PyObject *self, PyObject *args)
Guido van Rossumed233a51992-06-23 09:07:03 +0000177{
Guido van Rossumd20781b1998-07-02 02:53:36 +0000178#ifdef MS_WINDOWS
179 /* This would be an awful lot of stack space on Windows! */
180 pylist *rfd2obj, *wfd2obj, *efd2obj;
181#else
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000182 pylist rfd2obj[FD_SETSIZE + 3];
183 pylist wfd2obj[FD_SETSIZE + 3];
184 pylist efd2obj[FD_SETSIZE + 3];
Guido van Rossumd20781b1998-07-02 02:53:36 +0000185#endif
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000186 PyObject *ifdlist, *ofdlist, *efdlist;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000187 PyObject *ret = NULL;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000188 PyObject *tout = Py_None;
189 fd_set ifdset, ofdset, efdset;
190 double timeout;
191 struct timeval tv, *tvp;
Guido van Rossum3262e162000-06-28 21:18:13 +0000192 long seconds;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000193 int imax, omax, emax, max;
194 int n;
Guido van Rossumed233a51992-06-23 09:07:03 +0000195
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000196 /* convert arguments */
Guido van Rossum43713e52000-02-29 13:59:29 +0000197 if (!PyArg_ParseTuple(args, "OOO|O:select",
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000198 &ifdlist, &ofdlist, &efdlist, &tout))
199 return NULL;
Guido van Rossumed233a51992-06-23 09:07:03 +0000200
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000201 if (tout == Py_None)
202 tvp = (struct timeval *)0;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000203 else if (!PyArg_Parse(tout, "d", &timeout)) {
204 PyErr_SetString(PyExc_TypeError,
205 "timeout must be a float or None");
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000206 return NULL;
Barry Warsawc1cb3601996-12-12 22:16:21 +0000207 }
Guido van Rossumc7a22701993-11-01 16:27:16 +0000208 else {
Guido van Rossum3262e162000-06-28 21:18:13 +0000209 if (timeout > (double)LONG_MAX) {
210 PyErr_SetString(PyExc_OverflowError, "timeout period too long");
211 return NULL;
212 }
213 seconds = (long)timeout;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000214 timeout = timeout - (double)seconds;
215 tv.tv_sec = seconds;
Guido van Rossum3262e162000-06-28 21:18:13 +0000216 tv.tv_usec = (long)(timeout*1000000.0);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000217 tvp = &tv;
Guido van Rossumc7a22701993-11-01 16:27:16 +0000218 }
Guido van Rossumed233a51992-06-23 09:07:03 +0000219
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000220 /* sanity check first three arguments */
221 if (!PyList_Check(ifdlist) ||
222 !PyList_Check(ofdlist) ||
223 !PyList_Check(efdlist))
224 {
225 PyErr_SetString(PyExc_TypeError,
226 "arguments 1-3 must be lists");
227 return NULL;
228 }
Guido van Rossumed233a51992-06-23 09:07:03 +0000229
Guido van Rossumd20781b1998-07-02 02:53:36 +0000230#ifdef MS_WINDOWS
231 /* Allocate memory for the lists */
232 rfd2obj = PyMem_NEW(pylist, FD_SETSIZE + 3);
233 wfd2obj = PyMem_NEW(pylist, FD_SETSIZE + 3);
234 efd2obj = PyMem_NEW(pylist, FD_SETSIZE + 3);
235 if (rfd2obj == NULL || wfd2obj == NULL || efd2obj == NULL) {
Guido van Rossumb18618d2000-05-03 23:44:39 +0000236 if (rfd2obj) PyMem_DEL(rfd2obj);
237 if (wfd2obj) PyMem_DEL(wfd2obj);
238 if (efd2obj) PyMem_DEL(efd2obj);
Guido van Rossumd20781b1998-07-02 02:53:36 +0000239 return NULL;
240 }
241#endif
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000242 /* Convert lists to fd_sets, and get maximum fd number
243 * propagates the Python exception set in list2set()
244 */
Barry Warsawc1cb3601996-12-12 22:16:21 +0000245 rfd2obj[0].sentinel = -1;
246 wfd2obj[0].sentinel = -1;
247 efd2obj[0].sentinel = -1;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000248 if ((imax=list2set(ifdlist, &ifdset, rfd2obj)) < 0)
Barry Warsawc1cb3601996-12-12 22:16:21 +0000249 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000250 if ((omax=list2set(ofdlist, &ofdset, wfd2obj)) < 0)
Barry Warsawc1cb3601996-12-12 22:16:21 +0000251 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000252 if ((emax=list2set(efdlist, &efdset, efd2obj)) < 0)
Barry Warsawc1cb3601996-12-12 22:16:21 +0000253 goto finally;
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000254 max = imax;
255 if (omax > max) max = omax;
256 if (emax > max) max = emax;
Guido van Rossumed233a51992-06-23 09:07:03 +0000257
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000258 Py_BEGIN_ALLOW_THREADS
259 n = select(max, &ifdset, &ofdset, &efdset, tvp);
260 Py_END_ALLOW_THREADS
Guido van Rossumed233a51992-06-23 09:07:03 +0000261
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000262 if (n < 0) {
263 PyErr_SetFromErrno(SelectError);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000264 }
Barry Warsawc1cb3601996-12-12 22:16:21 +0000265 else if (n == 0) {
266 /* optimization */
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000267 ifdlist = PyList_New(0);
Barry Warsawc1cb3601996-12-12 22:16:21 +0000268 if (ifdlist) {
269 ret = Py_BuildValue("OOO", ifdlist, ifdlist, ifdlist);
270 Py_DECREF(ifdlist);
271 }
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000272 }
Barry Warsawc1cb3601996-12-12 22:16:21 +0000273 else {
274 /* any of these three calls can raise an exception. it's more
275 convenient to test for this after all three calls... but
276 is that acceptable?
277 */
278 ifdlist = set2list(&ifdset, rfd2obj);
279 ofdlist = set2list(&ofdset, wfd2obj);
280 efdlist = set2list(&efdset, efd2obj);
281 if (PyErr_Occurred())
282 ret = NULL;
283 else
284 ret = Py_BuildValue("OOO", ifdlist, ofdlist, efdlist);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000285
Barry Warsawc1cb3601996-12-12 22:16:21 +0000286 Py_DECREF(ifdlist);
287 Py_DECREF(ofdlist);
288 Py_DECREF(efdlist);
289 }
290
291 finally:
292 reap_obj(rfd2obj);
293 reap_obj(wfd2obj);
294 reap_obj(efd2obj);
Guido van Rossumd20781b1998-07-02 02:53:36 +0000295#ifdef MS_WINDOWS
296 PyMem_DEL(rfd2obj);
297 PyMem_DEL(wfd2obj);
298 PyMem_DEL(efd2obj);
299#endif
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000300 return ret;
Guido van Rossumed233a51992-06-23 09:07:03 +0000301}
302
Guido van Rossum1d8fb2d1998-06-28 16:54:49 +0000303static char select_doc[] =
304"select(rlist, wlist, xlist[, timeout]) -> (rlist, wlist, xlist)\n\
305\n\
306Wait until one or more file descriptors are ready for some kind of I/O.\n\
307The first three arguments are lists of file descriptors to be waited for:\n\
308rlist -- wait until ready for reading\n\
309wlist -- wait until ready for writing\n\
310xlist -- wait for an ``exceptional condition''\n\
311If only one kind of condition is required, pass [] for the other lists.\n\
312A file descriptor is either a socket or file object, or a small integer\n\
313gotten from a fileno() method call on one of those.\n\
314\n\
315The optional 4th argument specifies a timeout in seconds; it may be\n\
316a floating point number to specify fractions of seconds. If it is absent\n\
317or None, the call will never time out.\n\
318\n\
319The return value is a tuple of three lists corresponding to the first three\n\
320arguments; each contains the subset of the corresponding file descriptors\n\
321that are ready.\n\
322\n\
323*** IMPORTANT NOTICE ***\n\
324On Windows, only sockets are supported; on Unix, all file descriptors.";
325
Guido van Rossumed233a51992-06-23 09:07:03 +0000326
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000327static PyMethodDef select_methods[] = {
Guido van Rossum1d8fb2d1998-06-28 16:54:49 +0000328 {"select", select_select, 1, select_doc},
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000329 {0, 0}, /* sentinel */
Guido van Rossumed233a51992-06-23 09:07:03 +0000330};
331
Guido van Rossum1d8fb2d1998-06-28 16:54:49 +0000332static char module_doc[] =
333"This module supports asynchronous I/O on multiple file descriptors.\n\
334\n\
335*** IMPORTANT NOTICE ***\n\
336On Windows, only sockets are supported; on Unix, all file descriptors.";
Guido van Rossumed233a51992-06-23 09:07:03 +0000337
Guido van Rossum3886bb61998-12-04 18:50:17 +0000338DL_EXPORT(void)
Thomas Woutersf3f33dc2000-07-21 06:00:07 +0000339initselect(void)
Guido van Rossumed233a51992-06-23 09:07:03 +0000340{
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000341 PyObject *m, *d;
Guido van Rossum1d8fb2d1998-06-28 16:54:49 +0000342 m = Py_InitModule3("select", select_methods, module_doc);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000343 d = PyModule_GetDict(m);
Guido van Rossum0cb96de1997-10-01 04:29:29 +0000344 SelectError = PyErr_NewException("select.error", NULL, NULL);
Barry Warsawe4ac0aa1996-12-12 00:04:35 +0000345 PyDict_SetItemString(d, "error", SelectError);
Guido van Rossumed233a51992-06-23 09:07:03 +0000346}