source: vendor/python/2.5/Modules/selectmodule.c

Last change on this file was 3225, checked in by bird, 18 years ago

Python 2.5

File size: 17.5 KB
Line 
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*/
8
9#include "Python.h"
10
11#ifdef __APPLE__
12 /* Perform runtime testing for a broken poll on OSX to make it easier
13 * to use the same binary on multiple releases of the OS.
14 */
15#undef HAVE_BROKEN_POLL
16#endif
17
18/* Windows #defines FD_SETSIZE to 64 if FD_SETSIZE isn't already defined.
19 64 is too small (too many people have bumped into that limit).
20 Here we boost it.
21 Users who want even more than the boosted limit should #define
22 FD_SETSIZE higher before this; e.g., via compiler /D switch.
23*/
24#if defined(MS_WINDOWS) && !defined(FD_SETSIZE)
25#define FD_SETSIZE 512
26#endif
27
28#if defined(HAVE_POLL_H)
29#include <poll.h>
30#elif defined(HAVE_SYS_POLL_H)
31#include <sys/poll.h>
32#endif
33
34#ifdef __sgi
35/* This is missing from unistd.h */
36extern void bzero(void *, int);
37#endif
38
39#ifdef HAVE_SYS_TYPES_H
40#include <sys/types.h>
41#endif
42
43#if defined(PYOS_OS2) && !defined(PYCC_GCC)
44#include <sys/time.h>
45#include <utils.h>
46#endif
47
48#ifdef MS_WINDOWS
49# include <winsock.h>
50#else
51# define SOCKET int
52# ifdef __BEOS__
53# include <net/socket.h>
54# elif defined(__VMS)
55# include <socket.h>
56# endif
57#endif
58
59
60static PyObject *SelectError;
61
62/* list of Python objects and their file descriptor */
63typedef struct {
64 PyObject *obj; /* owned reference */
65 SOCKET fd;
66 int sentinel; /* -1 == sentinel */
67} pylist;
68
69static void
70reap_obj(pylist fd2obj[FD_SETSIZE + 1])
71{
72 int i;
73 for (i = 0; i < FD_SETSIZE + 1 && fd2obj[i].sentinel >= 0; i++) {
74 Py_XDECREF(fd2obj[i].obj);
75 fd2obj[i].obj = NULL;
76 }
77 fd2obj[0].sentinel = -1;
78}
79
80
81/* returns -1 and sets the Python exception if an error occurred, otherwise
82 returns a number >= 0
83*/
84static int
85seq2set(PyObject *seq, fd_set *set, pylist fd2obj[FD_SETSIZE + 1])
86{
87 int i;
88 int max = -1;
89 int index = 0;
90 int len = -1;
91 PyObject* fast_seq = NULL;
92 PyObject* o = NULL;
93
94 fd2obj[0].obj = (PyObject*)0; /* set list to zero size */
95 FD_ZERO(set);
96
97 fast_seq=PySequence_Fast(seq, "arguments 1-3 must be sequences");
98 if (!fast_seq)
99 return -1;
100
101 len = PySequence_Fast_GET_SIZE(fast_seq);
102
103 for (i = 0; i < len; i++) {
104 SOCKET v;
105
106 /* any intervening fileno() calls could decr this refcnt */
107 if (!(o = PySequence_Fast_GET_ITEM(fast_seq, i)))
108 return -1;
109
110 Py_INCREF(o);
111 v = PyObject_AsFileDescriptor( o );
112 if (v == -1) goto finally;
113
114#if defined(_MSC_VER)
115 max = 0; /* not used for Win32 */
116#else /* !_MSC_VER */
117 if (v < 0 || v >= FD_SETSIZE) {
118 PyErr_SetString(PyExc_ValueError,
119 "filedescriptor out of range in select()");
120 goto finally;
121 }
122 if (v > max)
123 max = v;
124#endif /* _MSC_VER */
125 FD_SET(v, set);
126
127 /* add object and its file descriptor to the list */
128 if (index >= FD_SETSIZE) {
129 PyErr_SetString(PyExc_ValueError,
130 "too many file descriptors in select()");
131 goto finally;
132 }
133 fd2obj[index].obj = o;
134 fd2obj[index].fd = v;
135 fd2obj[index].sentinel = 0;
136 fd2obj[++index].sentinel = -1;
137 }
138 Py_DECREF(fast_seq);
139 return max+1;
140
141 finally:
142 Py_XDECREF(o);
143 Py_DECREF(fast_seq);
144 return -1;
145}
146
147/* returns NULL and sets the Python exception if an error occurred */
148static PyObject *
149set2list(fd_set *set, pylist fd2obj[FD_SETSIZE + 1])
150{
151 int i, j, count=0;
152 PyObject *list, *o;
153 SOCKET fd;
154
155 for (j = 0; fd2obj[j].sentinel >= 0; j++) {
156 if (FD_ISSET(fd2obj[j].fd, set))
157 count++;
158 }
159 list = PyList_New(count);
160 if (!list)
161 return NULL;
162
163 i = 0;
164 for (j = 0; fd2obj[j].sentinel >= 0; j++) {
165 fd = fd2obj[j].fd;
166 if (FD_ISSET(fd, set)) {
167#ifndef _MSC_VER
168 if (fd > FD_SETSIZE) {
169 PyErr_SetString(PyExc_SystemError,
170 "filedescriptor out of range returned in select()");
171 goto finally;
172 }
173#endif
174 o = fd2obj[j].obj;
175 fd2obj[j].obj = NULL;
176 /* transfer ownership */
177 if (PyList_SetItem(list, i, o) < 0)
178 goto finally;
179
180 i++;
181 }
182 }
183 return list;
184 finally:
185 Py_DECREF(list);
186 return NULL;
187}
188
189#undef SELECT_USES_HEAP
190#if FD_SETSIZE > 1024
191#define SELECT_USES_HEAP
192#endif /* FD_SETSIZE > 1024 */
193
194static PyObject *
195select_select(PyObject *self, PyObject *args)
196{
197#ifdef SELECT_USES_HEAP
198 pylist *rfd2obj, *wfd2obj, *efd2obj;
199#else /* !SELECT_USES_HEAP */
200 /* XXX: All this should probably be implemented as follows:
201 * - find the highest descriptor we're interested in
202 * - add one
203 * - that's the size
204 * See: Stevens, APitUE, $12.5.1
205 */
206 pylist rfd2obj[FD_SETSIZE + 1];
207 pylist wfd2obj[FD_SETSIZE + 1];
208 pylist efd2obj[FD_SETSIZE + 1];
209#endif /* SELECT_USES_HEAP */
210 PyObject *ifdlist, *ofdlist, *efdlist;
211 PyObject *ret = NULL;
212 PyObject *tout = Py_None;
213 fd_set ifdset, ofdset, efdset;
214 double timeout;
215 struct timeval tv, *tvp;
216 long seconds;
217 int imax, omax, emax, max;
218 int n;
219
220 /* convert arguments */
221 if (!PyArg_UnpackTuple(args, "select", 3, 4,
222 &ifdlist, &ofdlist, &efdlist, &tout))
223 return NULL;
224
225 if (tout == Py_None)
226 tvp = (struct timeval *)0;
227 else if (!PyNumber_Check(tout)) {
228 PyErr_SetString(PyExc_TypeError,
229 "timeout must be a float or None");
230 return NULL;
231 }
232 else {
233 timeout = PyFloat_AsDouble(tout);
234 if (timeout == -1 && PyErr_Occurred())
235 return NULL;
236 if (timeout > (double)LONG_MAX) {
237 PyErr_SetString(PyExc_OverflowError,
238 "timeout period too long");
239 return NULL;
240 }
241 seconds = (long)timeout;
242 timeout = timeout - (double)seconds;
243 tv.tv_sec = seconds;
244 tv.tv_usec = (long)(timeout*1000000.0);
245 tvp = &tv;
246 }
247
248
249#ifdef SELECT_USES_HEAP
250 /* Allocate memory for the lists */
251 rfd2obj = PyMem_NEW(pylist, FD_SETSIZE + 1);
252 wfd2obj = PyMem_NEW(pylist, FD_SETSIZE + 1);
253 efd2obj = PyMem_NEW(pylist, FD_SETSIZE + 1);
254 if (rfd2obj == NULL || wfd2obj == NULL || efd2obj == NULL) {
255 if (rfd2obj) PyMem_DEL(rfd2obj);
256 if (wfd2obj) PyMem_DEL(wfd2obj);
257 if (efd2obj) PyMem_DEL(efd2obj);
258 return PyErr_NoMemory();
259 }
260#endif /* SELECT_USES_HEAP */
261 /* Convert sequences to fd_sets, and get maximum fd number
262 * propagates the Python exception set in seq2set()
263 */
264 rfd2obj[0].sentinel = -1;
265 wfd2obj[0].sentinel = -1;
266 efd2obj[0].sentinel = -1;
267 if ((imax=seq2set(ifdlist, &ifdset, rfd2obj)) < 0)
268 goto finally;
269 if ((omax=seq2set(ofdlist, &ofdset, wfd2obj)) < 0)
270 goto finally;
271 if ((emax=seq2set(efdlist, &efdset, efd2obj)) < 0)
272 goto finally;
273 max = imax;
274 if (omax > max) max = omax;
275 if (emax > max) max = emax;
276
277 Py_BEGIN_ALLOW_THREADS
278 n = select(max, &ifdset, &ofdset, &efdset, tvp);
279 Py_END_ALLOW_THREADS
280
281#ifdef MS_WINDOWS
282 if (n == SOCKET_ERROR) {
283 PyErr_SetExcFromWindowsErr(SelectError, WSAGetLastError());
284 }
285#else
286 if (n < 0) {
287 PyErr_SetFromErrno(SelectError);
288 }
289#endif
290 else if (n == 0) {
291 /* optimization */
292 ifdlist = PyList_New(0);
293 if (ifdlist) {
294 ret = PyTuple_Pack(3, ifdlist, ifdlist, ifdlist);
295 Py_DECREF(ifdlist);
296 }
297 }
298 else {
299 /* any of these three calls can raise an exception. it's more
300 convenient to test for this after all three calls... but
301 is that acceptable?
302 */
303 ifdlist = set2list(&ifdset, rfd2obj);
304 ofdlist = set2list(&ofdset, wfd2obj);
305 efdlist = set2list(&efdset, efd2obj);
306 if (PyErr_Occurred())
307 ret = NULL;
308 else
309 ret = PyTuple_Pack(3, ifdlist, ofdlist, efdlist);
310
311 Py_DECREF(ifdlist);
312 Py_DECREF(ofdlist);
313 Py_DECREF(efdlist);
314 }
315
316 finally:
317 reap_obj(rfd2obj);
318 reap_obj(wfd2obj);
319 reap_obj(efd2obj);
320#ifdef SELECT_USES_HEAP
321 PyMem_DEL(rfd2obj);
322 PyMem_DEL(wfd2obj);
323 PyMem_DEL(efd2obj);
324#endif /* SELECT_USES_HEAP */
325 return ret;
326}
327
328#if defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)
329/*
330 * poll() support
331 */
332
333typedef struct {
334 PyObject_HEAD
335 PyObject *dict;
336 int ufd_uptodate;
337 int ufd_len;
338 struct pollfd *ufds;
339} pollObject;
340
341static PyTypeObject poll_Type;
342
343/* Update the malloc'ed array of pollfds to match the dictionary
344 contained within a pollObject. Return 1 on success, 0 on an error.
345*/
346
347static int
348update_ufd_array(pollObject *self)
349{
350 Py_ssize_t i, pos;
351 PyObject *key, *value;
352
353 self->ufd_len = PyDict_Size(self->dict);
354 PyMem_Resize(self->ufds, struct pollfd, self->ufd_len);
355 if (self->ufds == NULL) {
356 PyErr_NoMemory();
357 return 0;
358 }
359
360 i = pos = 0;
361 while (PyDict_Next(self->dict, &pos, &key, &value)) {
362 self->ufds[i].fd = PyInt_AsLong(key);
363 self->ufds[i].events = (short)PyInt_AsLong(value);
364 i++;
365 }
366 self->ufd_uptodate = 1;
367 return 1;
368}
369
370PyDoc_STRVAR(poll_register_doc,
371"register(fd [, eventmask] ) -> None\n\n\
372Register a file descriptor with the polling object.\n\
373fd -- either an integer, or an object with a fileno() method returning an\n\
374 int.\n\
375events -- an optional bitmask describing the type of events to check for");
376
377static PyObject *
378poll_register(pollObject *self, PyObject *args)
379{
380 PyObject *o, *key, *value;
381 int fd, events = POLLIN | POLLPRI | POLLOUT;
382 int err;
383
384 if (!PyArg_ParseTuple(args, "O|i:register", &o, &events)) {
385 return NULL;
386 }
387
388 fd = PyObject_AsFileDescriptor(o);
389 if (fd == -1) return NULL;
390
391 /* Add entry to the internal dictionary: the key is the
392 file descriptor, and the value is the event mask. */
393 key = PyInt_FromLong(fd);
394 if (key == NULL)
395 return NULL;
396 value = PyInt_FromLong(events);
397 if (value == NULL) {
398 Py_DECREF(key);
399 return NULL;
400 }
401 err = PyDict_SetItem(self->dict, key, value);
402 Py_DECREF(key);
403 Py_DECREF(value);
404 if (err < 0)
405 return NULL;
406
407 self->ufd_uptodate = 0;
408
409 Py_INCREF(Py_None);
410 return Py_None;
411}
412
413PyDoc_STRVAR(poll_unregister_doc,
414"unregister(fd) -> None\n\n\
415Remove a file descriptor being tracked by the polling object.");
416
417static PyObject *
418poll_unregister(pollObject *self, PyObject *o)
419{
420 PyObject *key;
421 int fd;
422
423 fd = PyObject_AsFileDescriptor( o );
424 if (fd == -1)
425 return NULL;
426
427 /* Check whether the fd is already in the array */
428 key = PyInt_FromLong(fd);
429 if (key == NULL)
430 return NULL;
431
432 if (PyDict_DelItem(self->dict, key) == -1) {
433 Py_DECREF(key);
434 /* This will simply raise the KeyError set by PyDict_DelItem
435 if the file descriptor isn't registered. */
436 return NULL;
437 }
438
439 Py_DECREF(key);
440 self->ufd_uptodate = 0;
441
442 Py_INCREF(Py_None);
443 return Py_None;
444}
445
446PyDoc_STRVAR(poll_poll_doc,
447"poll( [timeout] ) -> list of (fd, event) 2-tuples\n\n\
448Polls the set of registered file descriptors, returning a list containing \n\
449any descriptors that have events or errors to report.");
450
451static PyObject *
452poll_poll(pollObject *self, PyObject *args)
453{
454 PyObject *result_list = NULL, *tout = NULL;
455 int timeout = 0, poll_result, i, j;
456 PyObject *value = NULL, *num = NULL;
457
458 if (!PyArg_UnpackTuple(args, "poll", 0, 1, &tout)) {
459 return NULL;
460 }
461
462 /* Check values for timeout */
463 if (tout == NULL || tout == Py_None)
464 timeout = -1;
465 else if (!PyNumber_Check(tout)) {
466 PyErr_SetString(PyExc_TypeError,
467 "timeout must be an integer or None");
468 return NULL;
469 }
470 else {
471 tout = PyNumber_Int(tout);
472 if (!tout)
473 return NULL;
474 timeout = PyInt_AsLong(tout);
475 Py_DECREF(tout);
476 if (timeout == -1 && PyErr_Occurred())
477 return NULL;
478 }
479
480 /* Ensure the ufd array is up to date */
481 if (!self->ufd_uptodate)
482 if (update_ufd_array(self) == 0)
483 return NULL;
484
485 /* call poll() */
486 Py_BEGIN_ALLOW_THREADS;
487 poll_result = poll(self->ufds, self->ufd_len, timeout);
488 Py_END_ALLOW_THREADS;
489
490 if (poll_result < 0) {
491 PyErr_SetFromErrno(SelectError);
492 return NULL;
493 }
494
495 /* build the result list */
496
497 result_list = PyList_New(poll_result);
498 if (!result_list)
499 return NULL;
500 else {
501 for (i = 0, j = 0; j < poll_result; j++) {
502 /* skip to the next fired descriptor */
503 while (!self->ufds[i].revents) {
504 i++;
505 }
506 /* if we hit a NULL return, set value to NULL
507 and break out of loop; code at end will
508 clean up result_list */
509 value = PyTuple_New(2);
510 if (value == NULL)
511 goto error;
512 num = PyInt_FromLong(self->ufds[i].fd);
513 if (num == NULL) {
514 Py_DECREF(value);
515 goto error;
516 }
517 PyTuple_SET_ITEM(value, 0, num);
518
519 /* The &0xffff is a workaround for AIX. 'revents'
520 is a 16-bit short, and IBM assigned POLLNVAL
521 to be 0x8000, so the conversion to int results
522 in a negative number. See SF bug #923315. */
523 num = PyInt_FromLong(self->ufds[i].revents & 0xffff);
524 if (num == NULL) {
525 Py_DECREF(value);
526 goto error;
527 }
528 PyTuple_SET_ITEM(value, 1, num);
529 if ((PyList_SetItem(result_list, j, value)) == -1) {
530 Py_DECREF(value);
531 goto error;
532 }
533 i++;
534 }
535 }
536 return result_list;
537
538 error:
539 Py_DECREF(result_list);
540 return NULL;
541}
542
543static PyMethodDef poll_methods[] = {
544 {"register", (PyCFunction)poll_register,
545 METH_VARARGS, poll_register_doc},
546 {"unregister", (PyCFunction)poll_unregister,
547 METH_O, poll_unregister_doc},
548 {"poll", (PyCFunction)poll_poll,
549 METH_VARARGS, poll_poll_doc},
550 {NULL, NULL} /* sentinel */
551};
552
553static pollObject *
554newPollObject(void)
555{
556 pollObject *self;
557 self = PyObject_New(pollObject, &poll_Type);
558 if (self == NULL)
559 return NULL;
560 /* ufd_uptodate is a Boolean, denoting whether the
561 array pointed to by ufds matches the contents of the dictionary. */
562 self->ufd_uptodate = 0;
563 self->ufds = NULL;
564 self->dict = PyDict_New();
565 if (self->dict == NULL) {
566 Py_DECREF(self);
567 return NULL;
568 }
569 return self;
570}
571
572static void
573poll_dealloc(pollObject *self)
574{
575 if (self->ufds != NULL)
576 PyMem_DEL(self->ufds);
577 Py_XDECREF(self->dict);
578 PyObject_Del(self);
579}
580
581static PyObject *
582poll_getattr(pollObject *self, char *name)
583{
584 return Py_FindMethod(poll_methods, (PyObject *)self, name);
585}
586
587static PyTypeObject poll_Type = {
588 /* The ob_type field must be initialized in the module init function
589 * to be portable to Windows without using C++. */
590 PyObject_HEAD_INIT(NULL)
591 0, /*ob_size*/
592 "select.poll", /*tp_name*/
593 sizeof(pollObject), /*tp_basicsize*/
594 0, /*tp_itemsize*/
595 /* methods */
596 (destructor)poll_dealloc, /*tp_dealloc*/
597 0, /*tp_print*/
598 (getattrfunc)poll_getattr, /*tp_getattr*/
599 0, /*tp_setattr*/
600 0, /*tp_compare*/
601 0, /*tp_repr*/
602 0, /*tp_as_number*/
603 0, /*tp_as_sequence*/
604 0, /*tp_as_mapping*/
605 0, /*tp_hash*/
606};
607
608PyDoc_STRVAR(poll_doc,
609"Returns a polling object, which supports registering and\n\
610unregistering file descriptors, and then polling them for I/O events.");
611
612static PyObject *
613select_poll(PyObject *self, PyObject *unused)
614{
615 return (PyObject *)newPollObject();
616}
617
618#ifdef __APPLE__
619/*
620 * On some systems poll() sets errno on invalid file descriptors. We test
621 * for this at runtime because this bug may be fixed or introduced between
622 * OS releases.
623 */
624static int select_have_broken_poll(void)
625{
626 int poll_test;
627 int filedes[2];
628
629 struct pollfd poll_struct = { 0, POLLIN|POLLPRI|POLLOUT, 0 };
630
631 /* Create a file descriptor to make invalid */
632 if (pipe(filedes) < 0) {
633 return 1;
634 }
635 poll_struct.fd = filedes[0];
636 close(filedes[0]);
637 close(filedes[1]);
638 poll_test = poll(&poll_struct, 1, 0);
639 if (poll_test < 0) {
640 return 1;
641 } else if (poll_test == 0 && poll_struct.revents != POLLNVAL) {
642 return 1;
643 }
644 return 0;
645}
646#endif /* __APPLE__ */
647
648#endif /* HAVE_POLL */
649
650PyDoc_STRVAR(select_doc,
651"select(rlist, wlist, xlist[, timeout]) -> (rlist, wlist, xlist)\n\
652\n\
653Wait until one or more file descriptors are ready for some kind of I/O.\n\
654The first three arguments are sequences of file descriptors to be waited for:\n\
655rlist -- wait until ready for reading\n\
656wlist -- wait until ready for writing\n\
657xlist -- wait for an ``exceptional condition''\n\
658If only one kind of condition is required, pass [] for the other lists.\n\
659A file descriptor is either a socket or file object, or a small integer\n\
660gotten from a fileno() method call on one of those.\n\
661\n\
662The optional 4th argument specifies a timeout in seconds; it may be\n\
663a floating point number to specify fractions of seconds. If it is absent\n\
664or None, the call will never time out.\n\
665\n\
666The return value is a tuple of three lists corresponding to the first three\n\
667arguments; each contains the subset of the corresponding file descriptors\n\
668that are ready.\n\
669\n\
670*** IMPORTANT NOTICE ***\n\
671On Windows and OpenVMS, only sockets are supported; on Unix, all file descriptors.");
672
673static PyMethodDef select_methods[] = {
674 {"select", select_select, METH_VARARGS, select_doc},
675#if defined(HAVE_POLL)
676 {"poll", select_poll, METH_NOARGS, poll_doc},
677#endif /* HAVE_POLL */
678 {0, 0}, /* sentinel */
679};
680
681PyDoc_STRVAR(module_doc,
682"This module supports asynchronous I/O on multiple file descriptors.\n\
683\n\
684*** IMPORTANT NOTICE ***\n\
685On Windows and OpenVMS, only sockets are supported; on Unix, all file descriptors.");
686
687PyMODINIT_FUNC
688initselect(void)
689{
690 PyObject *m;
691 m = Py_InitModule3("select", select_methods, module_doc);
692 if (m == NULL)
693 return;
694
695 SelectError = PyErr_NewException("select.error", NULL, NULL);
696 Py_INCREF(SelectError);
697 PyModule_AddObject(m, "error", SelectError);
698#if defined(HAVE_POLL)
699
700#ifdef __APPLE__
701 if (select_have_broken_poll()) {
702 if (PyObject_DelAttrString(m, "poll") == -1) {
703 PyErr_Clear();
704 }
705 } else {
706#else
707 {
708#endif
709 poll_Type.ob_type = &PyType_Type;
710 PyModule_AddIntConstant(m, "POLLIN", POLLIN);
711 PyModule_AddIntConstant(m, "POLLPRI", POLLPRI);
712 PyModule_AddIntConstant(m, "POLLOUT", POLLOUT);
713 PyModule_AddIntConstant(m, "POLLERR", POLLERR);
714 PyModule_AddIntConstant(m, "POLLHUP", POLLHUP);
715 PyModule_AddIntConstant(m, "POLLNVAL", POLLNVAL);
716
717#ifdef POLLRDNORM
718 PyModule_AddIntConstant(m, "POLLRDNORM", POLLRDNORM);
719#endif
720#ifdef POLLRDBAND
721 PyModule_AddIntConstant(m, "POLLRDBAND", POLLRDBAND);
722#endif
723#ifdef POLLWRNORM
724 PyModule_AddIntConstant(m, "POLLWRNORM", POLLWRNORM);
725#endif
726#ifdef POLLWRBAND
727 PyModule_AddIntConstant(m, "POLLWRBAND", POLLWRBAND);
728#endif
729#ifdef POLLMSG
730 PyModule_AddIntConstant(m, "POLLMSG", POLLMSG);
731#endif
732 }
733#endif /* HAVE_POLL */
734}
Note: See TracBrowser for help on using the repository browser.