This commit was manufactured by cvs2svn to create tag 'r22a4-fork'.
[python/dscho.git] / Modules / selectmodule.c
blobf02b15a8ae490d95c771eb80fe75c082d14457d8
1 /* select - Module containing unix select(2) call.
2 Under Unix, the file descriptors are small integers.
3 Under Win32, select only exists for sockets, and sockets may
4 have any value except INVALID_SOCKET.
5 Under BeOS, we suffer the same dichotomy as Win32; sockets can be anything
6 >= 0.
7 */
9 #include "Python.h"
11 /* Windows #defines FD_SETSIZE to 64 if FD_SETSIZE isn't already defined.
12 64 is too small (too many people have bumped into that limit).
13 Here we boost it.
14 Users who want even more than the boosted limit should #define
15 FD_SETSIZE higher before this; e.g., via compiler /D switch.
17 #if defined(MS_WINDOWS) && !defined(FD_SETSIZE)
18 #define FD_SETSIZE 512
19 #endif
21 #ifdef HAVE_UNISTD_H
22 #include <unistd.h>
23 #endif
24 #if defined(HAVE_POLL_H)
25 #include <poll.h>
26 #elif defined(HAVE_SYS_POLL_H)
27 #include <sys/poll.h>
28 #endif
30 #ifdef __sgi
31 /* This is missing from unistd.h */
32 extern void bzero(void *, int);
33 #endif
35 #ifndef DONT_HAVE_SYS_TYPES_H
36 #include <sys/types.h>
37 #endif
39 #if defined(PYOS_OS2)
40 #include <sys/time.h>
41 #include <utils.h>
42 #endif
44 #ifdef MS_WINDOWS
45 #include <winsock.h>
46 #else
47 #ifdef __BEOS__
48 #include <net/socket.h>
49 #define SOCKET int
50 #else
51 #define SOCKET int
52 #endif
53 #endif
55 #ifdef RISCOS
56 #define NO_DUP
57 #undef off_t
58 #undef uid_t
59 #undef gid_t
60 #undef errno
61 #include "socklib.h"
62 #endif /* RISCOS */
64 static PyObject *SelectError;
66 /* list of Python objects and their file descriptor */
67 typedef struct {
68 PyObject *obj; /* owned reference */
69 SOCKET fd;
70 int sentinel; /* -1 == sentinel */
71 } pylist;
73 static void
74 reap_obj(pylist fd2obj[FD_SETSIZE + 1])
76 int i;
77 for (i = 0; i < FD_SETSIZE + 1 && fd2obj[i].sentinel >= 0; i++) {
78 Py_XDECREF(fd2obj[i].obj);
79 fd2obj[i].obj = NULL;
81 fd2obj[0].sentinel = -1;
85 /* returns -1 and sets the Python exception if an error occurred, otherwise
86 returns a number >= 0
88 static int
89 list2set(PyObject *list, fd_set *set, pylist fd2obj[FD_SETSIZE + 1])
91 int i;
92 int max = -1;
93 int index = 0;
94 int len = PyList_Size(list);
95 PyObject* o = NULL;
97 fd2obj[0].obj = (PyObject*)0; /* set list to zero size */
98 FD_ZERO(set);
100 for (i = 0; i < len; i++) {
101 SOCKET v;
103 /* any intervening fileno() calls could decr this refcnt */
104 if (!(o = PyList_GetItem(list, i)))
105 return -1;
107 Py_INCREF(o);
108 v = PyObject_AsFileDescriptor( o );
109 if (v == -1) goto finally;
111 #if defined(_MSC_VER)
112 max = 0; /* not used for Win32 */
113 #else /* !_MSC_VER */
114 if (v < 0 || v >= FD_SETSIZE) {
115 PyErr_SetString(PyExc_ValueError,
116 "filedescriptor out of range in select()");
117 goto finally;
119 if (v > max)
120 max = v;
121 #endif /* _MSC_VER */
122 FD_SET(v, set);
124 /* add object and its file descriptor to the list */
125 if (index >= FD_SETSIZE) {
126 PyErr_SetString(PyExc_ValueError,
127 "too many file descriptors in select()");
128 goto finally;
130 fd2obj[index].obj = o;
131 fd2obj[index].fd = v;
132 fd2obj[index].sentinel = 0;
133 fd2obj[++index].sentinel = -1;
135 return max+1;
137 finally:
138 Py_XDECREF(o);
139 return -1;
142 /* returns NULL and sets the Python exception if an error occurred */
143 static PyObject *
144 set2list(fd_set *set, pylist fd2obj[FD_SETSIZE + 1])
146 int i, j, count=0;
147 PyObject *list, *o;
148 SOCKET fd;
150 for (j = 0; fd2obj[j].sentinel >= 0; j++) {
151 if (FD_ISSET(fd2obj[j].fd, set))
152 count++;
154 list = PyList_New(count);
155 if (!list)
156 return NULL;
158 i = 0;
159 for (j = 0; fd2obj[j].sentinel >= 0; j++) {
160 fd = fd2obj[j].fd;
161 if (FD_ISSET(fd, set)) {
162 #ifndef _MSC_VER
163 if (fd > FD_SETSIZE) {
164 PyErr_SetString(PyExc_SystemError,
165 "filedescriptor out of range returned in select()");
166 goto finally;
168 #endif
169 o = fd2obj[j].obj;
170 fd2obj[j].obj = NULL;
171 /* transfer ownership */
172 if (PyList_SetItem(list, i, o) < 0)
173 goto finally;
175 i++;
178 return list;
179 finally:
180 Py_DECREF(list);
181 return NULL;
184 #undef SELECT_USES_HEAP
185 #if FD_SETSIZE > 1024
186 #define SELECT_USES_HEAP
187 #endif /* FD_SETSIZE > 1024 */
189 static PyObject *
190 select_select(PyObject *self, PyObject *args)
192 #ifdef SELECT_USES_HEAP
193 pylist *rfd2obj, *wfd2obj, *efd2obj;
194 #else /* !SELECT_USES_HEAP */
195 /* XXX: All this should probably be implemented as follows:
196 * - find the highest descriptor we're interested in
197 * - add one
198 * - that's the size
199 * See: Stevens, APitUE, $12.5.1
201 pylist rfd2obj[FD_SETSIZE + 1];
202 pylist wfd2obj[FD_SETSIZE + 1];
203 pylist efd2obj[FD_SETSIZE + 1];
204 #endif /* SELECT_USES_HEAP */
205 PyObject *ifdlist, *ofdlist, *efdlist;
206 PyObject *ret = NULL;
207 PyObject *tout = Py_None;
208 fd_set ifdset, ofdset, efdset;
209 double timeout;
210 struct timeval tv, *tvp;
211 long seconds;
212 int imax, omax, emax, max;
213 int n;
215 /* convert arguments */
216 if (!PyArg_ParseTuple(args, "OOO|O:select",
217 &ifdlist, &ofdlist, &efdlist, &tout))
218 return NULL;
220 if (tout == Py_None)
221 tvp = (struct timeval *)0;
222 else if (!PyArg_Parse(tout, "d", &timeout)) {
223 PyErr_SetString(PyExc_TypeError,
224 "timeout must be a float or None");
225 return NULL;
227 else {
228 if (timeout > (double)LONG_MAX) {
229 PyErr_SetString(PyExc_OverflowError,
230 "timeout period too long");
231 return NULL;
233 seconds = (long)timeout;
234 timeout = timeout - (double)seconds;
235 tv.tv_sec = seconds;
236 tv.tv_usec = (long)(timeout*1000000.0);
237 tvp = &tv;
240 /* sanity check first three arguments */
241 if (!PyList_Check(ifdlist) ||
242 !PyList_Check(ofdlist) ||
243 !PyList_Check(efdlist))
245 PyErr_SetString(PyExc_TypeError,
246 "arguments 1-3 must be lists");
247 return NULL;
250 #ifdef SELECT_USES_HEAP
251 /* Allocate memory for the lists */
252 rfd2obj = PyMem_NEW(pylist, FD_SETSIZE + 1);
253 wfd2obj = PyMem_NEW(pylist, FD_SETSIZE + 1);
254 efd2obj = PyMem_NEW(pylist, FD_SETSIZE + 1);
255 if (rfd2obj == NULL || wfd2obj == NULL || efd2obj == NULL) {
256 if (rfd2obj) PyMem_DEL(rfd2obj);
257 if (wfd2obj) PyMem_DEL(wfd2obj);
258 if (efd2obj) PyMem_DEL(efd2obj);
259 return NULL;
261 #endif /* SELECT_USES_HEAP */
262 /* Convert lists to fd_sets, and get maximum fd number
263 * propagates the Python exception set in list2set()
265 rfd2obj[0].sentinel = -1;
266 wfd2obj[0].sentinel = -1;
267 efd2obj[0].sentinel = -1;
268 if ((imax=list2set(ifdlist, &ifdset, rfd2obj)) < 0)
269 goto finally;
270 if ((omax=list2set(ofdlist, &ofdset, wfd2obj)) < 0)
271 goto finally;
272 if ((emax=list2set(efdlist, &efdset, efd2obj)) < 0)
273 goto finally;
274 max = imax;
275 if (omax > max) max = omax;
276 if (emax > max) max = emax;
278 Py_BEGIN_ALLOW_THREADS
279 n = select(max, &ifdset, &ofdset, &efdset, tvp);
280 Py_END_ALLOW_THREADS
282 if (n < 0) {
283 PyErr_SetFromErrno(SelectError);
285 else if (n == 0) {
286 /* optimization */
287 ifdlist = PyList_New(0);
288 if (ifdlist) {
289 ret = Py_BuildValue("OOO", ifdlist, ifdlist, ifdlist);
290 Py_DECREF(ifdlist);
293 else {
294 /* any of these three calls can raise an exception. it's more
295 convenient to test for this after all three calls... but
296 is that acceptable?
298 ifdlist = set2list(&ifdset, rfd2obj);
299 ofdlist = set2list(&ofdset, wfd2obj);
300 efdlist = set2list(&efdset, efd2obj);
301 if (PyErr_Occurred())
302 ret = NULL;
303 else
304 ret = Py_BuildValue("OOO", ifdlist, ofdlist, efdlist);
306 Py_DECREF(ifdlist);
307 Py_DECREF(ofdlist);
308 Py_DECREF(efdlist);
311 finally:
312 reap_obj(rfd2obj);
313 reap_obj(wfd2obj);
314 reap_obj(efd2obj);
315 #ifdef SELECT_USES_HEAP
316 PyMem_DEL(rfd2obj);
317 PyMem_DEL(wfd2obj);
318 PyMem_DEL(efd2obj);
319 #endif /* SELECT_USES_HEAP */
320 return ret;
323 #ifdef HAVE_POLL
325 * poll() support
328 typedef struct {
329 PyObject_HEAD
330 PyObject *dict;
331 int ufd_uptodate;
332 int ufd_len;
333 struct pollfd *ufds;
334 } pollObject;
336 staticforward PyTypeObject poll_Type;
338 /* Update the malloc'ed array of pollfds to match the dictionary
339 contained within a pollObject. Return 1 on success, 0 on an error.
342 static int
343 update_ufd_array(pollObject *self)
345 int i, pos;
346 PyObject *key, *value;
348 self->ufd_len = PyDict_Size(self->dict);
349 PyMem_Resize(self->ufds, struct pollfd, self->ufd_len);
350 if (self->ufds == NULL) {
351 PyErr_NoMemory();
352 return 0;
355 i = pos = 0;
356 while (PyDict_Next(self->dict, &pos, &key, &value)) {
357 self->ufds[i].fd = PyInt_AsLong(key);
358 self->ufds[i].events = (short)PyInt_AsLong(value);
359 i++;
361 self->ufd_uptodate = 1;
362 return 1;
365 static char poll_register_doc[] =
366 "register(fd [, eventmask] ) -> None\n\n\
367 Register a file descriptor with the polling object.\n\
368 fd -- either an integer, or an object with a fileno() method returning an\n\
369 int.\n\
370 events -- an optional bitmask describing the type of events to check for";
372 static PyObject *
373 poll_register(pollObject *self, PyObject *args)
375 PyObject *o, *key, *value;
376 int fd, events = POLLIN | POLLPRI | POLLOUT;
378 if (!PyArg_ParseTuple(args, "O|i:register", &o, &events)) {
379 return NULL;
382 fd = PyObject_AsFileDescriptor(o);
383 if (fd == -1) return NULL;
385 /* Add entry to the internal dictionary: the key is the
386 file descriptor, and the value is the event mask. */
387 if ( (NULL == (key = PyInt_FromLong(fd))) ||
388 (NULL == (value = PyInt_FromLong(events))) ||
389 (PyDict_SetItem(self->dict, key, value)) == -1) {
390 return NULL;
392 self->ufd_uptodate = 0;
394 Py_INCREF(Py_None);
395 return Py_None;
398 static char poll_unregister_doc[] =
399 "unregister(fd) -> None\n\n\
400 Remove a file descriptor being tracked by the polling object.";
402 static PyObject *
403 poll_unregister(pollObject *self, PyObject *args)
405 PyObject *o, *key;
406 int fd;
408 if (!PyArg_ParseTuple(args, "O:unregister", &o)) {
409 return NULL;
412 fd = PyObject_AsFileDescriptor( o );
413 if (fd == -1)
414 return NULL;
416 /* Check whether the fd is already in the array */
417 key = PyInt_FromLong(fd);
418 if (key == NULL)
419 return NULL;
421 if (PyDict_DelItem(self->dict, key) == -1) {
422 Py_DECREF(key);
423 /* This will simply raise the KeyError set by PyDict_DelItem
424 if the file descriptor isn't registered. */
425 return NULL;
428 Py_DECREF(key);
429 self->ufd_uptodate = 0;
431 Py_INCREF(Py_None);
432 return Py_None;
435 static char poll_poll_doc[] =
436 "poll( [timeout] ) -> list of (fd, event) 2-tuples\n\n\
437 Polls the set of registered file descriptors, returning a list containing \n\
438 any descriptors that have events or errors to report.";
440 static PyObject *
441 poll_poll(pollObject *self, PyObject *args)
443 PyObject *result_list = NULL, *tout = NULL;
444 int timeout = 0, poll_result, i, j;
445 PyObject *value = NULL, *num = NULL;
447 if (!PyArg_ParseTuple(args, "|O:poll", &tout)) {
448 return NULL;
451 /* Check values for timeout */
452 if (tout == NULL || tout == Py_None)
453 timeout = -1;
454 else if (!PyArg_Parse(tout, "i", &timeout)) {
455 PyErr_SetString(PyExc_TypeError,
456 "timeout must be an integer or None");
457 return NULL;
460 /* Ensure the ufd array is up to date */
461 if (!self->ufd_uptodate)
462 if (update_ufd_array(self) == 0)
463 return NULL;
465 /* call poll() */
466 Py_BEGIN_ALLOW_THREADS;
467 poll_result = poll(self->ufds, self->ufd_len, timeout);
468 Py_END_ALLOW_THREADS;
470 if (poll_result < 0) {
471 PyErr_SetFromErrno(SelectError);
472 return NULL;
475 /* build the result list */
477 result_list = PyList_New(poll_result);
478 if (!result_list)
479 return NULL;
480 else {
481 for (i = 0, j = 0; j < poll_result; j++) {
482 /* skip to the next fired descriptor */
483 while (!self->ufds[i].revents) {
484 i++;
486 /* if we hit a NULL return, set value to NULL
487 and break out of loop; code at end will
488 clean up result_list */
489 value = PyTuple_New(2);
490 if (value == NULL)
491 goto error;
492 num = PyInt_FromLong(self->ufds[i].fd);
493 if (num == NULL) {
494 Py_DECREF(value);
495 goto error;
497 PyTuple_SET_ITEM(value, 0, num);
499 num = PyInt_FromLong(self->ufds[i].revents);
500 if (num == NULL) {
501 Py_DECREF(value);
502 goto error;
504 PyTuple_SET_ITEM(value, 1, num);
505 if ((PyList_SetItem(result_list, j, value)) == -1) {
506 Py_DECREF(value);
507 goto error;
509 i++;
512 return result_list;
514 error:
515 Py_DECREF(result_list);
516 return NULL;
519 static PyMethodDef poll_methods[] = {
520 {"register", (PyCFunction)poll_register,
521 METH_VARARGS, poll_register_doc},
522 {"unregister", (PyCFunction)poll_unregister,
523 METH_VARARGS, poll_unregister_doc},
524 {"poll", (PyCFunction)poll_poll,
525 METH_VARARGS, poll_poll_doc},
526 {NULL, NULL} /* sentinel */
529 static pollObject *
530 newPollObject(void)
532 pollObject *self;
533 self = PyObject_New(pollObject, &poll_Type);
534 if (self == NULL)
535 return NULL;
536 /* ufd_uptodate is a Boolean, denoting whether the
537 array pointed to by ufds matches the contents of the dictionary. */
538 self->ufd_uptodate = 0;
539 self->ufds = NULL;
540 self->dict = PyDict_New();
541 if (self->dict == NULL) {
542 Py_DECREF(self);
543 return NULL;
545 return self;
548 static void
549 poll_dealloc(pollObject *self)
551 if (self->ufds != NULL)
552 PyMem_DEL(self->ufds);
553 Py_XDECREF(self->dict);
554 PyObject_Del(self);
557 static PyObject *
558 poll_getattr(pollObject *self, char *name)
560 return Py_FindMethod(poll_methods, (PyObject *)self, name);
563 statichere PyTypeObject poll_Type = {
564 /* The ob_type field must be initialized in the module init function
565 * to be portable to Windows without using C++. */
566 PyObject_HEAD_INIT(NULL)
567 0, /*ob_size*/
568 "poll", /*tp_name*/
569 sizeof(pollObject), /*tp_basicsize*/
570 0, /*tp_itemsize*/
571 /* methods */
572 (destructor)poll_dealloc, /*tp_dealloc*/
573 0, /*tp_print*/
574 (getattrfunc)poll_getattr, /*tp_getattr*/
575 0, /*tp_setattr*/
576 0, /*tp_compare*/
577 0, /*tp_repr*/
578 0, /*tp_as_number*/
579 0, /*tp_as_sequence*/
580 0, /*tp_as_mapping*/
581 0, /*tp_hash*/
584 static char poll_doc[] =
585 "Returns a polling object, which supports registering and\n\
586 unregistering file descriptors, and then polling them for I/O events.";
588 static PyObject *
589 select_poll(PyObject *self, PyObject *args)
591 pollObject *rv;
593 if (!PyArg_ParseTuple(args, ":poll"))
594 return NULL;
595 rv = newPollObject();
596 if ( rv == NULL )
597 return NULL;
598 return (PyObject *)rv;
600 #endif /* HAVE_POLL */
602 static char select_doc[] =
603 "select(rlist, wlist, xlist[, timeout]) -> (rlist, wlist, xlist)\n\
605 Wait until one or more file descriptors are ready for some kind of I/O.\n\
606 The first three arguments are lists of file descriptors to be waited for:\n\
607 rlist -- wait until ready for reading\n\
608 wlist -- wait until ready for writing\n\
609 xlist -- wait for an ``exceptional condition''\n\
610 If only one kind of condition is required, pass [] for the other lists.\n\
611 A file descriptor is either a socket or file object, or a small integer\n\
612 gotten from a fileno() method call on one of those.\n\
614 The optional 4th argument specifies a timeout in seconds; it may be\n\
615 a floating point number to specify fractions of seconds. If it is absent\n\
616 or None, the call will never time out.\n\
618 The return value is a tuple of three lists corresponding to the first three\n\
619 arguments; each contains the subset of the corresponding file descriptors\n\
620 that are ready.\n\
622 *** IMPORTANT NOTICE ***\n\
623 On Windows, only sockets are supported; on Unix, all file descriptors.";
625 static PyMethodDef select_methods[] = {
626 {"select", select_select, METH_VARARGS, select_doc},
627 #ifdef HAVE_POLL
628 {"poll", select_poll, METH_VARARGS, poll_doc},
629 #endif /* HAVE_POLL */
630 {0, 0}, /* sentinel */
633 static char module_doc[] =
634 "This module supports asynchronous I/O on multiple file descriptors.\n\
636 *** IMPORTANT NOTICE ***\n\
637 On Windows, only sockets are supported; on Unix, all file descriptors.";
640 * Convenience routine to export an integer value.
641 * For simplicity, errors (which are unlikely anyway) are ignored.
644 static void
645 insint(PyObject *d, char *name, int value)
647 PyObject *v = PyInt_FromLong((long) value);
648 if (v == NULL) {
649 /* Don't bother reporting this error */
650 PyErr_Clear();
652 else {
653 PyDict_SetItemString(d, name, v);
654 Py_DECREF(v);
658 DL_EXPORT(void)
659 initselect(void)
661 PyObject *m, *d;
662 m = Py_InitModule3("select", select_methods, module_doc);
663 d = PyModule_GetDict(m);
664 SelectError = PyErr_NewException("select.error", NULL, NULL);
665 PyDict_SetItemString(d, "error", SelectError);
666 #ifdef HAVE_POLL
667 poll_Type.ob_type = &PyType_Type;
668 insint(d, "POLLIN", POLLIN);
669 insint(d, "POLLPRI", POLLPRI);
670 insint(d, "POLLOUT", POLLOUT);
671 insint(d, "POLLERR", POLLERR);
672 insint(d, "POLLHUP", POLLHUP);
673 insint(d, "POLLNVAL", POLLNVAL);
675 #ifdef POLLRDNORM
676 insint(d, "POLLRDNORM", POLLRDNORM);
677 #endif
678 #ifdef POLLRDBAND
679 insint(d, "POLLRDBAND", POLLRDBAND);
680 #endif
681 #ifdef POLLWRNORM
682 insint(d, "POLLWRNORM", POLLWRNORM);
683 #endif
684 #ifdef POLLWRBAND
685 insint(d, "POLLWRBAND", POLLWRBAND);
686 #endif
687 #ifdef POLLMSG
688 insint(d, "POLLMSG", POLLMSG);
689 #endif
690 #endif /* HAVE_POLL */