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 */
|
---|
36 | extern 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 |
|
---|
60 | static PyObject *SelectError;
|
---|
61 |
|
---|
62 | /* list of Python objects and their file descriptor */
|
---|
63 | typedef struct {
|
---|
64 | PyObject *obj; /* owned reference */
|
---|
65 | SOCKET fd;
|
---|
66 | int sentinel; /* -1 == sentinel */
|
---|
67 | } pylist;
|
---|
68 |
|
---|
69 | static void
|
---|
70 | reap_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 | */
|
---|
84 | static int
|
---|
85 | seq2set(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 */
|
---|
148 | static PyObject *
|
---|
149 | set2list(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 |
|
---|
194 | static PyObject *
|
---|
195 | select_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 |
|
---|
333 | typedef struct {
|
---|
334 | PyObject_HEAD
|
---|
335 | PyObject *dict;
|
---|
336 | int ufd_uptodate;
|
---|
337 | int ufd_len;
|
---|
338 | struct pollfd *ufds;
|
---|
339 | } pollObject;
|
---|
340 |
|
---|
341 | static 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 |
|
---|
347 | static int
|
---|
348 | update_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 |
|
---|
370 | PyDoc_STRVAR(poll_register_doc,
|
---|
371 | "register(fd [, eventmask] ) -> None\n\n\
|
---|
372 | Register a file descriptor with the polling object.\n\
|
---|
373 | fd -- either an integer, or an object with a fileno() method returning an\n\
|
---|
374 | int.\n\
|
---|
375 | events -- an optional bitmask describing the type of events to check for");
|
---|
376 |
|
---|
377 | static PyObject *
|
---|
378 | poll_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 |
|
---|
413 | PyDoc_STRVAR(poll_unregister_doc,
|
---|
414 | "unregister(fd) -> None\n\n\
|
---|
415 | Remove a file descriptor being tracked by the polling object.");
|
---|
416 |
|
---|
417 | static PyObject *
|
---|
418 | poll_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 |
|
---|
446 | PyDoc_STRVAR(poll_poll_doc,
|
---|
447 | "poll( [timeout] ) -> list of (fd, event) 2-tuples\n\n\
|
---|
448 | Polls the set of registered file descriptors, returning a list containing \n\
|
---|
449 | any descriptors that have events or errors to report.");
|
---|
450 |
|
---|
451 | static PyObject *
|
---|
452 | poll_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 |
|
---|
543 | static 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 |
|
---|
553 | static pollObject *
|
---|
554 | newPollObject(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 |
|
---|
572 | static void
|
---|
573 | poll_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 |
|
---|
581 | static PyObject *
|
---|
582 | poll_getattr(pollObject *self, char *name)
|
---|
583 | {
|
---|
584 | return Py_FindMethod(poll_methods, (PyObject *)self, name);
|
---|
585 | }
|
---|
586 |
|
---|
587 | static 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 |
|
---|
608 | PyDoc_STRVAR(poll_doc,
|
---|
609 | "Returns a polling object, which supports registering and\n\
|
---|
610 | unregistering file descriptors, and then polling them for I/O events.");
|
---|
611 |
|
---|
612 | static PyObject *
|
---|
613 | select_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 | */
|
---|
624 | static 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 |
|
---|
650 | PyDoc_STRVAR(select_doc,
|
---|
651 | "select(rlist, wlist, xlist[, timeout]) -> (rlist, wlist, xlist)\n\
|
---|
652 | \n\
|
---|
653 | Wait until one or more file descriptors are ready for some kind of I/O.\n\
|
---|
654 | The first three arguments are sequences of file descriptors to be waited for:\n\
|
---|
655 | rlist -- wait until ready for reading\n\
|
---|
656 | wlist -- wait until ready for writing\n\
|
---|
657 | xlist -- wait for an ``exceptional condition''\n\
|
---|
658 | If only one kind of condition is required, pass [] for the other lists.\n\
|
---|
659 | A file descriptor is either a socket or file object, or a small integer\n\
|
---|
660 | gotten from a fileno() method call on one of those.\n\
|
---|
661 | \n\
|
---|
662 | The optional 4th argument specifies a timeout in seconds; it may be\n\
|
---|
663 | a floating point number to specify fractions of seconds. If it is absent\n\
|
---|
664 | or None, the call will never time out.\n\
|
---|
665 | \n\
|
---|
666 | The return value is a tuple of three lists corresponding to the first three\n\
|
---|
667 | arguments; each contains the subset of the corresponding file descriptors\n\
|
---|
668 | that are ready.\n\
|
---|
669 | \n\
|
---|
670 | *** IMPORTANT NOTICE ***\n\
|
---|
671 | On Windows and OpenVMS, only sockets are supported; on Unix, all file descriptors.");
|
---|
672 |
|
---|
673 | static 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 |
|
---|
681 | PyDoc_STRVAR(module_doc,
|
---|
682 | "This module supports asynchronous I/O on multiple file descriptors.\n\
|
---|
683 | \n\
|
---|
684 | *** IMPORTANT NOTICE ***\n\
|
---|
685 | On Windows and OpenVMS, only sockets are supported; on Unix, all file descriptors.");
|
---|
686 |
|
---|
687 | PyMODINIT_FUNC
|
---|
688 | initselect(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 | }
|
---|