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
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).
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
21 #if defined(HAVE_POLL_H)
23 #elif defined(HAVE_SYS_POLL_H)
28 /* This is missing from unistd.h */
29 extern void bzero(void *, int);
32 #ifndef DONT_HAVE_SYS_TYPES_H
33 #include <sys/types.h>
36 #if defined(PYOS_OS2) && !defined(PYCC_GCC)
45 #include <net/socket.h>
53 static PyObject
*SelectError
;
55 /* list of Python objects and their file descriptor */
57 PyObject
*obj
; /* owned reference */
59 int sentinel
; /* -1 == sentinel */
63 reap_obj(pylist fd2obj
[FD_SETSIZE
+ 1])
66 for (i
= 0; i
< FD_SETSIZE
+ 1 && fd2obj
[i
].sentinel
>= 0; i
++) {
67 Py_XDECREF(fd2obj
[i
].obj
);
70 fd2obj
[0].sentinel
= -1;
74 /* returns -1 and sets the Python exception if an error occurred, otherwise
78 list2set(PyObject
*list
, fd_set
*set
, pylist fd2obj
[FD_SETSIZE
+ 1])
83 int len
= PyList_Size(list
);
86 fd2obj
[0].obj
= (PyObject
*)0; /* set list to zero size */
89 for (i
= 0; i
< len
; i
++) {
92 /* any intervening fileno() calls could decr this refcnt */
93 if (!(o
= PyList_GetItem(list
, i
)))
97 v
= PyObject_AsFileDescriptor( o
);
98 if (v
== -1) goto finally
;
100 #if defined(_MSC_VER)
101 max
= 0; /* not used for Win32 */
102 #else /* !_MSC_VER */
103 if (v
< 0 || v
>= FD_SETSIZE
) {
104 PyErr_SetString(PyExc_ValueError
,
105 "filedescriptor out of range in select()");
110 #endif /* _MSC_VER */
113 /* add object and its file descriptor to the list */
114 if (index
>= FD_SETSIZE
) {
115 PyErr_SetString(PyExc_ValueError
,
116 "too many file descriptors in select()");
119 fd2obj
[index
].obj
= o
;
120 fd2obj
[index
].fd
= v
;
121 fd2obj
[index
].sentinel
= 0;
122 fd2obj
[++index
].sentinel
= -1;
131 /* returns NULL and sets the Python exception if an error occurred */
133 set2list(fd_set
*set
, pylist fd2obj
[FD_SETSIZE
+ 1])
139 for (j
= 0; fd2obj
[j
].sentinel
>= 0; j
++) {
140 if (FD_ISSET(fd2obj
[j
].fd
, set
))
143 list
= PyList_New(count
);
148 for (j
= 0; fd2obj
[j
].sentinel
>= 0; j
++) {
150 if (FD_ISSET(fd
, set
)) {
152 if (fd
> FD_SETSIZE
) {
153 PyErr_SetString(PyExc_SystemError
,
154 "filedescriptor out of range returned in select()");
159 fd2obj
[j
].obj
= NULL
;
160 /* transfer ownership */
161 if (PyList_SetItem(list
, i
, o
) < 0)
173 #undef SELECT_USES_HEAP
174 #if FD_SETSIZE > 1024
175 #define SELECT_USES_HEAP
176 #endif /* FD_SETSIZE > 1024 */
179 select_select(PyObject
*self
, PyObject
*args
)
181 #ifdef SELECT_USES_HEAP
182 pylist
*rfd2obj
, *wfd2obj
, *efd2obj
;
183 #else /* !SELECT_USES_HEAP */
184 /* XXX: All this should probably be implemented as follows:
185 * - find the highest descriptor we're interested in
188 * See: Stevens, APitUE, $12.5.1
190 pylist rfd2obj
[FD_SETSIZE
+ 1];
191 pylist wfd2obj
[FD_SETSIZE
+ 1];
192 pylist efd2obj
[FD_SETSIZE
+ 1];
193 #endif /* SELECT_USES_HEAP */
194 PyObject
*ifdlist
, *ofdlist
, *efdlist
;
195 PyObject
*ret
= NULL
;
196 PyObject
*tout
= Py_None
;
197 fd_set ifdset
, ofdset
, efdset
;
199 struct timeval tv
, *tvp
;
201 int imax
, omax
, emax
, max
;
204 /* convert arguments */
205 if (!PyArg_ParseTuple(args
, "OOO|O:select",
206 &ifdlist
, &ofdlist
, &efdlist
, &tout
))
210 tvp
= (struct timeval
*)0;
211 else if (!PyNumber_Check(tout
)) {
212 PyErr_SetString(PyExc_TypeError
,
213 "timeout must be a float or None");
217 timeout
= PyFloat_AsDouble(tout
);
218 if (timeout
== -1 && PyErr_Occurred())
220 if (timeout
> (double)LONG_MAX
) {
221 PyErr_SetString(PyExc_OverflowError
,
222 "timeout period too long");
225 seconds
= (long)timeout
;
226 timeout
= timeout
- (double)seconds
;
228 tv
.tv_usec
= (long)(timeout
*1000000.0);
232 /* sanity check first three arguments */
233 if (!PyList_Check(ifdlist
) ||
234 !PyList_Check(ofdlist
) ||
235 !PyList_Check(efdlist
))
237 PyErr_SetString(PyExc_TypeError
,
238 "arguments 1-3 must be lists");
242 #ifdef SELECT_USES_HEAP
243 /* Allocate memory for the lists */
244 rfd2obj
= PyMem_NEW(pylist
, FD_SETSIZE
+ 1);
245 wfd2obj
= PyMem_NEW(pylist
, FD_SETSIZE
+ 1);
246 efd2obj
= PyMem_NEW(pylist
, FD_SETSIZE
+ 1);
247 if (rfd2obj
== NULL
|| wfd2obj
== NULL
|| efd2obj
== NULL
) {
248 if (rfd2obj
) PyMem_DEL(rfd2obj
);
249 if (wfd2obj
) PyMem_DEL(wfd2obj
);
250 if (efd2obj
) PyMem_DEL(efd2obj
);
251 return PyErr_NoMemory();
253 #endif /* SELECT_USES_HEAP */
254 /* Convert lists to fd_sets, and get maximum fd number
255 * propagates the Python exception set in list2set()
257 rfd2obj
[0].sentinel
= -1;
258 wfd2obj
[0].sentinel
= -1;
259 efd2obj
[0].sentinel
= -1;
260 if ((imax
=list2set(ifdlist
, &ifdset
, rfd2obj
)) < 0)
262 if ((omax
=list2set(ofdlist
, &ofdset
, wfd2obj
)) < 0)
264 if ((emax
=list2set(efdlist
, &efdset
, efd2obj
)) < 0)
267 if (omax
> max
) max
= omax
;
268 if (emax
> max
) max
= emax
;
270 Py_BEGIN_ALLOW_THREADS
271 n
= select(max
, &ifdset
, &ofdset
, &efdset
, tvp
);
275 if (n
== SOCKET_ERROR
) {
276 PyErr_SetExcFromWindowsErr(SelectError
, WSAGetLastError());
280 PyErr_SetFromErrno(SelectError
);
285 ifdlist
= PyList_New(0);
287 ret
= Py_BuildValue("OOO", ifdlist
, ifdlist
, ifdlist
);
292 /* any of these three calls can raise an exception. it's more
293 convenient to test for this after all three calls... but
296 ifdlist
= set2list(&ifdset
, rfd2obj
);
297 ofdlist
= set2list(&ofdset
, wfd2obj
);
298 efdlist
= set2list(&efdset
, efd2obj
);
299 if (PyErr_Occurred())
302 ret
= Py_BuildValue("OOO", ifdlist
, ofdlist
, efdlist
);
313 #ifdef SELECT_USES_HEAP
317 #endif /* SELECT_USES_HEAP */
321 #if defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)
334 static PyTypeObject poll_Type
;
336 /* Update the malloc'ed array of pollfds to match the dictionary
337 contained within a pollObject. Return 1 on success, 0 on an error.
341 update_ufd_array(pollObject
*self
)
344 PyObject
*key
, *value
;
346 self
->ufd_len
= PyDict_Size(self
->dict
);
347 PyMem_Resize(self
->ufds
, struct pollfd
, self
->ufd_len
);
348 if (self
->ufds
== NULL
) {
354 while (PyDict_Next(self
->dict
, &pos
, &key
, &value
)) {
355 self
->ufds
[i
].fd
= PyInt_AsLong(key
);
356 self
->ufds
[i
].events
= (short)PyInt_AsLong(value
);
359 self
->ufd_uptodate
= 1;
363 PyDoc_STRVAR(poll_register_doc
,
364 "register(fd [, eventmask] ) -> None\n\n\
365 Register a file descriptor with the polling object.\n\
366 fd -- either an integer, or an object with a fileno() method returning an\n\
368 events -- an optional bitmask describing the type of events to check for");
371 poll_register(pollObject
*self
, PyObject
*args
)
373 PyObject
*o
, *key
, *value
;
374 int fd
, events
= POLLIN
| POLLPRI
| POLLOUT
;
377 if (!PyArg_ParseTuple(args
, "O|i:register", &o
, &events
)) {
381 fd
= PyObject_AsFileDescriptor(o
);
382 if (fd
== -1) return NULL
;
384 /* Add entry to the internal dictionary: the key is the
385 file descriptor, and the value is the event mask. */
386 key
= PyInt_FromLong(fd
);
389 value
= PyInt_FromLong(events
);
394 err
= PyDict_SetItem(self
->dict
, key
, value
);
400 self
->ufd_uptodate
= 0;
406 PyDoc_STRVAR(poll_unregister_doc
,
407 "unregister(fd) -> None\n\n\
408 Remove a file descriptor being tracked by the polling object.");
411 poll_unregister(pollObject
*self
, PyObject
*args
)
416 if (!PyArg_ParseTuple(args
, "O:unregister", &o
)) {
420 fd
= PyObject_AsFileDescriptor( o
);
424 /* Check whether the fd is already in the array */
425 key
= PyInt_FromLong(fd
);
429 if (PyDict_DelItem(self
->dict
, key
) == -1) {
431 /* This will simply raise the KeyError set by PyDict_DelItem
432 if the file descriptor isn't registered. */
437 self
->ufd_uptodate
= 0;
443 PyDoc_STRVAR(poll_poll_doc
,
444 "poll( [timeout] ) -> list of (fd, event) 2-tuples\n\n\
445 Polls the set of registered file descriptors, returning a list containing \n\
446 any descriptors that have events or errors to report.");
449 poll_poll(pollObject
*self
, PyObject
*args
)
451 PyObject
*result_list
= NULL
, *tout
= NULL
;
452 int timeout
= 0, poll_result
, i
, j
;
453 PyObject
*value
= NULL
, *num
= NULL
;
455 if (!PyArg_ParseTuple(args
, "|O:poll", &tout
)) {
459 /* Check values for timeout */
460 if (tout
== NULL
|| tout
== Py_None
)
462 else if (!PyNumber_Check(tout
)) {
463 PyErr_SetString(PyExc_TypeError
,
464 "timeout must be an integer or None");
468 tout
= PyNumber_Int(tout
);
471 timeout
= PyInt_AsLong(tout
);
475 /* Ensure the ufd array is up to date */
476 if (!self
->ufd_uptodate
)
477 if (update_ufd_array(self
) == 0)
481 Py_BEGIN_ALLOW_THREADS
;
482 poll_result
= poll(self
->ufds
, self
->ufd_len
, timeout
);
483 Py_END_ALLOW_THREADS
;
485 if (poll_result
< 0) {
486 PyErr_SetFromErrno(SelectError
);
490 /* build the result list */
492 result_list
= PyList_New(poll_result
);
496 for (i
= 0, j
= 0; j
< poll_result
; j
++) {
497 /* skip to the next fired descriptor */
498 while (!self
->ufds
[i
].revents
) {
501 /* if we hit a NULL return, set value to NULL
502 and break out of loop; code at end will
503 clean up result_list */
504 value
= PyTuple_New(2);
507 num
= PyInt_FromLong(self
->ufds
[i
].fd
);
512 PyTuple_SET_ITEM(value
, 0, num
);
514 num
= PyInt_FromLong(self
->ufds
[i
].revents
);
519 PyTuple_SET_ITEM(value
, 1, num
);
520 if ((PyList_SetItem(result_list
, j
, value
)) == -1) {
530 Py_DECREF(result_list
);
534 static PyMethodDef poll_methods
[] = {
535 {"register", (PyCFunction
)poll_register
,
536 METH_VARARGS
, poll_register_doc
},
537 {"unregister", (PyCFunction
)poll_unregister
,
538 METH_VARARGS
, poll_unregister_doc
},
539 {"poll", (PyCFunction
)poll_poll
,
540 METH_VARARGS
, poll_poll_doc
},
541 {NULL
, NULL
} /* sentinel */
548 self
= PyObject_New(pollObject
, &poll_Type
);
551 /* ufd_uptodate is a Boolean, denoting whether the
552 array pointed to by ufds matches the contents of the dictionary. */
553 self
->ufd_uptodate
= 0;
555 self
->dict
= PyDict_New();
556 if (self
->dict
== NULL
) {
564 poll_dealloc(pollObject
*self
)
566 if (self
->ufds
!= NULL
)
567 PyMem_DEL(self
->ufds
);
568 Py_XDECREF(self
->dict
);
573 poll_getattr(pollObject
*self
, char *name
)
575 return Py_FindMethod(poll_methods
, (PyObject
*)self
, name
);
578 static PyTypeObject poll_Type
= {
579 /* The ob_type field must be initialized in the module init function
580 * to be portable to Windows without using C++. */
581 PyObject_HEAD_INIT(NULL
)
583 "select.poll", /*tp_name*/
584 sizeof(pollObject
), /*tp_basicsize*/
587 (destructor
)poll_dealloc
, /*tp_dealloc*/
589 (getattrfunc
)poll_getattr
, /*tp_getattr*/
594 0, /*tp_as_sequence*/
599 PyDoc_STRVAR(poll_doc
,
600 "Returns a polling object, which supports registering and\n\
601 unregistering file descriptors, and then polling them for I/O events.");
604 select_poll(PyObject
*self
, PyObject
*args
)
608 if (!PyArg_ParseTuple(args
, ":poll"))
610 rv
= newPollObject();
613 return (PyObject
*)rv
;
615 #endif /* HAVE_POLL && !HAVE_BROKEN_POLL */
617 PyDoc_STRVAR(select_doc
,
618 "select(rlist, wlist, xlist[, timeout]) -> (rlist, wlist, xlist)\n\
620 Wait until one or more file descriptors are ready for some kind of I/O.\n\
621 The first three arguments are lists of file descriptors to be waited for:\n\
622 rlist -- wait until ready for reading\n\
623 wlist -- wait until ready for writing\n\
624 xlist -- wait for an ``exceptional condition''\n\
625 If only one kind of condition is required, pass [] for the other lists.\n\
626 A file descriptor is either a socket or file object, or a small integer\n\
627 gotten from a fileno() method call on one of those.\n\
629 The optional 4th argument specifies a timeout in seconds; it may be\n\
630 a floating point number to specify fractions of seconds. If it is absent\n\
631 or None, the call will never time out.\n\
633 The return value is a tuple of three lists corresponding to the first three\n\
634 arguments; each contains the subset of the corresponding file descriptors\n\
637 *** IMPORTANT NOTICE ***\n\
638 On Windows, only sockets are supported; on Unix, all file descriptors.");
640 static PyMethodDef select_methods
[] = {
641 {"select", select_select
, METH_VARARGS
, select_doc
},
642 #if defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)
643 {"poll", select_poll
, METH_VARARGS
, poll_doc
},
644 #endif /* HAVE_POLL && !HAVE_BROKEN_POLL */
645 {0, 0}, /* sentinel */
648 PyDoc_STRVAR(module_doc
,
649 "This module supports asynchronous I/O on multiple file descriptors.\n\
651 *** IMPORTANT NOTICE ***\n\
652 On Windows, only sockets are supported; on Unix, all file descriptors.");
658 m
= Py_InitModule3("select", select_methods
, module_doc
);
660 SelectError
= PyErr_NewException("select.error", NULL
, NULL
);
661 Py_INCREF(SelectError
);
662 PyModule_AddObject(m
, "error", SelectError
);
663 #if defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)
664 poll_Type
.ob_type
= &PyType_Type
;
665 PyModule_AddIntConstant(m
, "POLLIN", POLLIN
);
666 PyModule_AddIntConstant(m
, "POLLPRI", POLLPRI
);
667 PyModule_AddIntConstant(m
, "POLLOUT", POLLOUT
);
668 PyModule_AddIntConstant(m
, "POLLERR", POLLERR
);
669 PyModule_AddIntConstant(m
, "POLLHUP", POLLHUP
);
670 PyModule_AddIntConstant(m
, "POLLNVAL", POLLNVAL
);
673 PyModule_AddIntConstant(m
, "POLLRDNORM", POLLRDNORM
);
676 PyModule_AddIntConstant(m
, "POLLRDBAND", POLLRDBAND
);
679 PyModule_AddIntConstant(m
, "POLLWRNORM", POLLWRNORM
);
682 PyModule_AddIntConstant(m
, "POLLWRBAND", POLLWRBAND
);
685 PyModule_AddIntConstant(m
, "POLLMSG", POLLMSG
);
687 #endif /* HAVE_POLL && !HAVE_BROKEN_POLL */