]> git.proxmox.com Git - mirror_edk2.git/blame - AppPkg/Applications/Python/PyMod-2.7.2/Modules/selectmodule.c
EADK (StdLib, AppPkg, StdLibPrivateInternalFiles): Python Beta Release.
[mirror_edk2.git] / AppPkg / Applications / Python / PyMod-2.7.2 / Modules / selectmodule.c
CommitLineData
b410d6e4 1/* select - Module containing unix select(2) call.\r
2 Under Unix, the file descriptors are small integers.\r
3 Under Win32, select only exists for sockets, and sockets may\r
4 have any value except INVALID_SOCKET.\r
5 Under BeOS, we suffer the same dichotomy as Win32; sockets can be anything\r
6 >= 0.\r
7*/\r
8\r
9#include "Python.h"\r
10#include <structmember.h>\r
11\r
12#ifdef __APPLE__\r
13 /* Perform runtime testing for a broken poll on OSX to make it easier\r
14 * to use the same binary on multiple releases of the OS.\r
15 */\r
16#undef HAVE_BROKEN_POLL\r
17#endif\r
18\r
19/* Windows #defines FD_SETSIZE to 64 if FD_SETSIZE isn't already defined.\r
20 64 is too small (too many people have bumped into that limit).\r
21 Here we boost it.\r
22 Users who want even more than the boosted limit should #define\r
23 FD_SETSIZE higher before this; e.g., via compiler /D switch.\r
24*/\r
25#if defined(MS_WINDOWS) && !defined(FD_SETSIZE)\r
26#define FD_SETSIZE 512\r
27#endif\r
28\r
29#if defined(HAVE_POLL_H)\r
30#include <poll.h>\r
31#elif defined(HAVE_SYS_POLL_H)\r
32#include <sys/poll.h>\r
33#endif\r
34\r
35#ifdef __sgi\r
36/* This is missing from unistd.h */\r
37extern void bzero(void *, int);\r
38#endif\r
39\r
40#ifdef HAVE_SYS_TYPES_H\r
41#include <sys/types.h>\r
42#endif\r
43\r
44#if defined(PYOS_OS2) && !defined(PYCC_GCC)\r
45#include <sys/time.h>\r
46#include <utils.h>\r
47#endif\r
48\r
49#ifdef MS_WINDOWS\r
50# include <winsock2.h>\r
51#else\r
52# define SOCKET int\r
53# ifdef __BEOS__\r
54# include <net/socket.h>\r
55# elif defined(__VMS)\r
56# include <socket.h>\r
57# endif\r
58#endif\r
59\r
60static PyObject *SelectError;\r
61\r
62/* list of Python objects and their file descriptor */\r
63typedef struct {\r
64 PyObject *obj; /* owned reference */\r
65 SOCKET fd;\r
66 int sentinel; /* -1 == sentinel */\r
67} pylist;\r
68\r
69static void\r
70reap_obj(pylist fd2obj[FD_SETSIZE + 1])\r
71{\r
72 int i;\r
73 for (i = 0; i < FD_SETSIZE + 1 && fd2obj[i].sentinel >= 0; i++) {\r
74 Py_XDECREF(fd2obj[i].obj);\r
75 fd2obj[i].obj = NULL;\r
76 }\r
77 fd2obj[0].sentinel = -1;\r
78}\r
79\r
80\r
81/* returns -1 and sets the Python exception if an error occurred, otherwise\r
82 returns a number >= 0\r
83*/\r
84static int\r
85seq2set(PyObject *seq, fd_set *set, pylist fd2obj[FD_SETSIZE + 1])\r
86{\r
87 int i;\r
88 int max = -1;\r
89 int index = 0;\r
90 int len = -1;\r
91 PyObject* fast_seq = NULL;\r
92 PyObject* o = NULL;\r
93\r
94 fd2obj[0].obj = (PyObject*)0; /* set list to zero size */\r
95 FD_ZERO(set);\r
96\r
97 fast_seq = PySequence_Fast(seq, "arguments 1-3 must be sequences");\r
98 if (!fast_seq)\r
99 return -1;\r
100\r
101 len = PySequence_Fast_GET_SIZE(fast_seq);\r
102\r
103 for (i = 0; i < len; i++) {\r
104 SOCKET v;\r
105\r
106 /* any intervening fileno() calls could decr this refcnt */\r
107 if (!(o = PySequence_Fast_GET_ITEM(fast_seq, i)))\r
108 return -1;\r
109\r
110 Py_INCREF(o);\r
111 v = PyObject_AsFileDescriptor( o );\r
112 if (v == -1) goto finally;\r
113\r
d78fab6b 114#if defined(_MSC_VER) && !defined(UEFI_C_SOURCE)\r
b410d6e4 115 max = 0; /* not used for Win32 */\r
116#else /* !_MSC_VER */\r
117 if (v < 0 || v >= FD_SETSIZE) {\r
118 PyErr_SetString(PyExc_ValueError,\r
119 "filedescriptor out of range in select()");\r
120 goto finally;\r
121 }\r
122 if (v > max)\r
123 max = v;\r
124#endif /* _MSC_VER */\r
125 FD_SET(v, set);\r
126\r
127 /* add object and its file descriptor to the list */\r
128 if (index >= FD_SETSIZE) {\r
129 PyErr_SetString(PyExc_ValueError,\r
130 "too many file descriptors in select()");\r
131 goto finally;\r
132 }\r
133 fd2obj[index].obj = o;\r
134 fd2obj[index].fd = v;\r
135 fd2obj[index].sentinel = 0;\r
136 fd2obj[++index].sentinel = -1;\r
137 }\r
138 Py_DECREF(fast_seq);\r
139 return max+1;\r
140\r
141 finally:\r
142 Py_XDECREF(o);\r
143 Py_DECREF(fast_seq);\r
144 return -1;\r
145}\r
146\r
147/* returns NULL and sets the Python exception if an error occurred */\r
148static PyObject *\r
149set2list(fd_set *set, pylist fd2obj[FD_SETSIZE + 1])\r
150{\r
151 int i, j, count=0;\r
152 PyObject *list, *o;\r
153 SOCKET fd;\r
154\r
155 for (j = 0; fd2obj[j].sentinel >= 0; j++) {\r
156 if (FD_ISSET(fd2obj[j].fd, set))\r
157 count++;\r
158 }\r
159 list = PyList_New(count);\r
160 if (!list)\r
161 return NULL;\r
162\r
163 i = 0;\r
164 for (j = 0; fd2obj[j].sentinel >= 0; j++) {\r
165 fd = fd2obj[j].fd;\r
166 if (FD_ISSET(fd, set)) {\r
d78fab6b 167#if !defined(_MSC_VER) || defined(UEFI_C_SOURCE)\r
b410d6e4 168 if (fd > FD_SETSIZE) {\r
169 PyErr_SetString(PyExc_SystemError,\r
170 "filedescriptor out of range returned in select()");\r
171 goto finally;\r
172 }\r
173#endif\r
174 o = fd2obj[j].obj;\r
175 fd2obj[j].obj = NULL;\r
176 /* transfer ownership */\r
177 if (PyList_SetItem(list, i, o) < 0)\r
178 goto finally;\r
179\r
180 i++;\r
181 }\r
182 }\r
183 return list;\r
184 finally:\r
185 Py_DECREF(list);\r
186 return NULL;\r
187}\r
188\r
189#undef SELECT_USES_HEAP\r
190#if FD_SETSIZE > 1024\r
191#define SELECT_USES_HEAP\r
192#endif /* FD_SETSIZE > 1024 */\r
193\r
194static PyObject *\r
195select_select(PyObject *self, PyObject *args)\r
196{\r
197#ifdef SELECT_USES_HEAP\r
198 pylist *rfd2obj, *wfd2obj, *efd2obj;\r
199#else /* !SELECT_USES_HEAP */\r
200 /* XXX: All this should probably be implemented as follows:\r
201 * - find the highest descriptor we're interested in\r
202 * - add one\r
203 * - that's the size\r
204 * See: Stevens, APitUE, $12.5.1\r
205 */\r
206 pylist rfd2obj[FD_SETSIZE + 1];\r
207 pylist wfd2obj[FD_SETSIZE + 1];\r
208 pylist efd2obj[FD_SETSIZE + 1];\r
209#endif /* SELECT_USES_HEAP */\r
210 PyObject *ifdlist, *ofdlist, *efdlist;\r
211 PyObject *ret = NULL;\r
212 PyObject *tout = Py_None;\r
213 fd_set ifdset, ofdset, efdset;\r
214 double timeout;\r
215 struct timeval tv, *tvp;\r
216 long seconds;\r
217 int imax, omax, emax, max;\r
218 int n;\r
219\r
220 /* convert arguments */\r
221 if (!PyArg_UnpackTuple(args, "select", 3, 4,\r
222 &ifdlist, &ofdlist, &efdlist, &tout))\r
223 return NULL;\r
224\r
225 if (tout == Py_None)\r
226 tvp = (struct timeval *)0;\r
227 else if (!PyNumber_Check(tout)) {\r
228 PyErr_SetString(PyExc_TypeError,\r
229 "timeout must be a float or None");\r
230 return NULL;\r
231 }\r
232 else {\r
233 timeout = PyFloat_AsDouble(tout);\r
234 if (timeout == -1 && PyErr_Occurred())\r
235 return NULL;\r
236 if (timeout > (double)LONG_MAX) {\r
237 PyErr_SetString(PyExc_OverflowError,\r
238 "timeout period too long");\r
239 return NULL;\r
240 }\r
241 seconds = (long)timeout;\r
242 timeout = timeout - (double)seconds;\r
243 tv.tv_sec = seconds;\r
244 tv.tv_usec = (long)(timeout * 1E6);\r
245 tvp = &tv;\r
246 }\r
247\r
248\r
249#ifdef SELECT_USES_HEAP\r
250 /* Allocate memory for the lists */\r
251 rfd2obj = PyMem_NEW(pylist, FD_SETSIZE + 1);\r
252 wfd2obj = PyMem_NEW(pylist, FD_SETSIZE + 1);\r
253 efd2obj = PyMem_NEW(pylist, FD_SETSIZE + 1);\r
254 if (rfd2obj == NULL || wfd2obj == NULL || efd2obj == NULL) {\r
255 if (rfd2obj) PyMem_DEL(rfd2obj);\r
256 if (wfd2obj) PyMem_DEL(wfd2obj);\r
257 if (efd2obj) PyMem_DEL(efd2obj);\r
258 return PyErr_NoMemory();\r
259 }\r
260#endif /* SELECT_USES_HEAP */\r
261 /* Convert sequences to fd_sets, and get maximum fd number\r
262 * propagates the Python exception set in seq2set()\r
263 */\r
264 rfd2obj[0].sentinel = -1;\r
265 wfd2obj[0].sentinel = -1;\r
266 efd2obj[0].sentinel = -1;\r
267 if ((imax=seq2set(ifdlist, &ifdset, rfd2obj)) < 0)\r
268 goto finally;\r
269 if ((omax=seq2set(ofdlist, &ofdset, wfd2obj)) < 0)\r
270 goto finally;\r
271 if ((emax=seq2set(efdlist, &efdset, efd2obj)) < 0)\r
272 goto finally;\r
273 max = imax;\r
274 if (omax > max) max = omax;\r
275 if (emax > max) max = emax;\r
276\r
277 Py_BEGIN_ALLOW_THREADS\r
278 n = select(max, &ifdset, &ofdset, &efdset, tvp);\r
279 Py_END_ALLOW_THREADS\r
280\r
281#ifdef MS_WINDOWS\r
282 if (n == SOCKET_ERROR) {\r
283 PyErr_SetExcFromWindowsErr(SelectError, WSAGetLastError());\r
284 }\r
285#else\r
286 if (n < 0) {\r
287 PyErr_SetFromErrno(SelectError);\r
288 }\r
289#endif\r
290 else {\r
291 /* any of these three calls can raise an exception. it's more\r
292 convenient to test for this after all three calls... but\r
293 is that acceptable?\r
294 */\r
295 ifdlist = set2list(&ifdset, rfd2obj);\r
296 ofdlist = set2list(&ofdset, wfd2obj);\r
297 efdlist = set2list(&efdset, efd2obj);\r
298 if (PyErr_Occurred())\r
299 ret = NULL;\r
300 else\r
301 ret = PyTuple_Pack(3, ifdlist, ofdlist, efdlist);\r
302\r
303 Py_DECREF(ifdlist);\r
304 Py_DECREF(ofdlist);\r
305 Py_DECREF(efdlist);\r
306 }\r
307\r
308 finally:\r
309 reap_obj(rfd2obj);\r
310 reap_obj(wfd2obj);\r
311 reap_obj(efd2obj);\r
312#ifdef SELECT_USES_HEAP\r
313 PyMem_DEL(rfd2obj);\r
314 PyMem_DEL(wfd2obj);\r
315 PyMem_DEL(efd2obj);\r
316#endif /* SELECT_USES_HEAP */\r
317 return ret;\r
318}\r
319\r
320#if defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL)\r
321/*\r
322 * poll() support\r
323 */\r
324\r
325typedef struct {\r
326 PyObject_HEAD\r
327 PyObject *dict;\r
328 int ufd_uptodate;\r
329 int ufd_len;\r
330 struct pollfd *ufds;\r
331} pollObject;\r
332\r
333static PyTypeObject poll_Type;\r
334\r
335/* Update the malloc'ed array of pollfds to match the dictionary\r
336 contained within a pollObject. Return 1 on success, 0 on an error.\r
337*/\r
338\r
339static int\r
340update_ufd_array(pollObject *self)\r
341{\r
342 Py_ssize_t i, pos;\r
343 PyObject *key, *value;\r
344 struct pollfd *old_ufds = self->ufds;\r
345\r
346 self->ufd_len = PyDict_Size(self->dict);\r
347 PyMem_RESIZE(self->ufds, struct pollfd, self->ufd_len);\r
348 if (self->ufds == NULL) {\r
349 self->ufds = old_ufds;\r
350 PyErr_NoMemory();\r
351 return 0;\r
352 }\r
353\r
354 i = pos = 0;\r
355 while (PyDict_Next(self->dict, &pos, &key, &value)) {\r
356 self->ufds[i].fd = PyInt_AsLong(key);\r
357 self->ufds[i].events = (short)PyInt_AsLong(value);\r
358 i++;\r
359 }\r
360 self->ufd_uptodate = 1;\r
361 return 1;\r
362}\r
363\r
364PyDoc_STRVAR(poll_register_doc,\r
365"register(fd [, eventmask] ) -> None\n\n\\r
366Register a file descriptor with the polling object.\n\\r
367fd -- either an integer, or an object with a fileno() method returning an\n\\r
368 int.\n\\r
369events -- an optional bitmask describing the type of events to check for");\r
370\r
371static PyObject *\r
372poll_register(pollObject *self, PyObject *args)\r
373{\r
374 PyObject *o, *key, *value;\r
375 int fd, events = POLLIN | POLLPRI | POLLOUT;\r
376 int err;\r
377\r
378 if (!PyArg_ParseTuple(args, "O|i:register", &o, &events)) {\r
379 return NULL;\r
380 }\r
381\r
382 fd = PyObject_AsFileDescriptor(o);\r
383 if (fd == -1) return NULL;\r
384\r
385 /* Add entry to the internal dictionary: the key is the\r
386 file descriptor, and the value is the event mask. */\r
387 key = PyInt_FromLong(fd);\r
388 if (key == NULL)\r
389 return NULL;\r
390 value = PyInt_FromLong(events);\r
391 if (value == NULL) {\r
392 Py_DECREF(key);\r
393 return NULL;\r
394 }\r
395 err = PyDict_SetItem(self->dict, key, value);\r
396 Py_DECREF(key);\r
397 Py_DECREF(value);\r
398 if (err < 0)\r
399 return NULL;\r
400\r
401 self->ufd_uptodate = 0;\r
402\r
403 Py_INCREF(Py_None);\r
404 return Py_None;\r
405}\r
406\r
407PyDoc_STRVAR(poll_modify_doc,\r
408"modify(fd, eventmask) -> None\n\n\\r
409Modify an already registered file descriptor.\n\\r
410fd -- either an integer, or an object with a fileno() method returning an\n\\r
411 int.\n\\r
412events -- an optional bitmask describing the type of events to check for");\r
413\r
414static PyObject *\r
415poll_modify(pollObject *self, PyObject *args)\r
416{\r
417 PyObject *o, *key, *value;\r
418 int fd, events;\r
419 int err;\r
420\r
421 if (!PyArg_ParseTuple(args, "Oi:modify", &o, &events)) {\r
422 return NULL;\r
423 }\r
424\r
425 fd = PyObject_AsFileDescriptor(o);\r
426 if (fd == -1) return NULL;\r
427\r
428 /* Modify registered fd */\r
429 key = PyInt_FromLong(fd);\r
430 if (key == NULL)\r
431 return NULL;\r
432 if (PyDict_GetItem(self->dict, key) == NULL) {\r
433 errno = ENOENT;\r
434 PyErr_SetFromErrno(PyExc_IOError);\r
435 return NULL;\r
436 }\r
437 value = PyInt_FromLong(events);\r
438 if (value == NULL) {\r
439 Py_DECREF(key);\r
440 return NULL;\r
441 }\r
442 err = PyDict_SetItem(self->dict, key, value);\r
443 Py_DECREF(key);\r
444 Py_DECREF(value);\r
445 if (err < 0)\r
446 return NULL;\r
447\r
448 self->ufd_uptodate = 0;\r
449\r
450 Py_INCREF(Py_None);\r
451 return Py_None;\r
452}\r
453\r
454\r
455PyDoc_STRVAR(poll_unregister_doc,\r
456"unregister(fd) -> None\n\n\\r
457Remove a file descriptor being tracked by the polling object.");\r
458\r
459static PyObject *\r
460poll_unregister(pollObject *self, PyObject *o)\r
461{\r
462 PyObject *key;\r
463 int fd;\r
464\r
465 fd = PyObject_AsFileDescriptor( o );\r
466 if (fd == -1)\r
467 return NULL;\r
468\r
469 /* Check whether the fd is already in the array */\r
470 key = PyInt_FromLong(fd);\r
471 if (key == NULL)\r
472 return NULL;\r
473\r
474 if (PyDict_DelItem(self->dict, key) == -1) {\r
475 Py_DECREF(key);\r
476 /* This will simply raise the KeyError set by PyDict_DelItem\r
477 if the file descriptor isn't registered. */\r
478 return NULL;\r
479 }\r
480\r
481 Py_DECREF(key);\r
482 self->ufd_uptodate = 0;\r
483\r
484 Py_INCREF(Py_None);\r
485 return Py_None;\r
486}\r
487\r
488PyDoc_STRVAR(poll_poll_doc,\r
489"poll( [timeout] ) -> list of (fd, event) 2-tuples\n\n\\r
490Polls the set of registered file descriptors, returning a list containing \n\\r
491any descriptors that have events or errors to report.");\r
492\r
493static PyObject *\r
494poll_poll(pollObject *self, PyObject *args)\r
495{\r
496 PyObject *result_list = NULL, *tout = NULL;\r
497 int timeout = 0, poll_result, i, j;\r
498 PyObject *value = NULL, *num = NULL;\r
499\r
500 if (!PyArg_UnpackTuple(args, "poll", 0, 1, &tout)) {\r
501 return NULL;\r
502 }\r
503\r
504 /* Check values for timeout */\r
505 if (tout == NULL || tout == Py_None)\r
506 timeout = -1;\r
507 else if (!PyNumber_Check(tout)) {\r
508 PyErr_SetString(PyExc_TypeError,\r
509 "timeout must be an integer or None");\r
510 return NULL;\r
511 }\r
512 else {\r
513 tout = PyNumber_Int(tout);\r
514 if (!tout)\r
515 return NULL;\r
516 timeout = PyInt_AsLong(tout);\r
517 Py_DECREF(tout);\r
518 if (timeout == -1 && PyErr_Occurred())\r
519 return NULL;\r
520 }\r
521\r
522 /* Ensure the ufd array is up to date */\r
523 if (!self->ufd_uptodate)\r
524 if (update_ufd_array(self) == 0)\r
525 return NULL;\r
526\r
527 /* call poll() */\r
528 Py_BEGIN_ALLOW_THREADS\r
529 poll_result = poll(self->ufds, self->ufd_len, timeout);\r
530 Py_END_ALLOW_THREADS\r
531\r
532 if (poll_result < 0) {\r
533 PyErr_SetFromErrno(SelectError);\r
534 return NULL;\r
535 }\r
536\r
537 /* build the result list */\r
538\r
539 result_list = PyList_New(poll_result);\r
540 if (!result_list)\r
541 return NULL;\r
542 else {\r
543 for (i = 0, j = 0; j < poll_result; j++) {\r
544 /* skip to the next fired descriptor */\r
545 while (!self->ufds[i].revents) {\r
546 i++;\r
547 }\r
548 /* if we hit a NULL return, set value to NULL\r
549 and break out of loop; code at end will\r
550 clean up result_list */\r
551 value = PyTuple_New(2);\r
552 if (value == NULL)\r
553 goto error;\r
554 num = PyInt_FromLong(self->ufds[i].fd);\r
555 if (num == NULL) {\r
556 Py_DECREF(value);\r
557 goto error;\r
558 }\r
559 PyTuple_SET_ITEM(value, 0, num);\r
560\r
561 /* The &0xffff is a workaround for AIX. 'revents'\r
562 is a 16-bit short, and IBM assigned POLLNVAL\r
563 to be 0x8000, so the conversion to int results\r
564 in a negative number. See SF bug #923315. */\r
565 num = PyInt_FromLong(self->ufds[i].revents & 0xffff);\r
566 if (num == NULL) {\r
567 Py_DECREF(value);\r
568 goto error;\r
569 }\r
570 PyTuple_SET_ITEM(value, 1, num);\r
571 if ((PyList_SetItem(result_list, j, value)) == -1) {\r
572 Py_DECREF(value);\r
573 goto error;\r
574 }\r
575 i++;\r
576 }\r
577 }\r
578 return result_list;\r
579\r
580 error:\r
581 Py_DECREF(result_list);\r
582 return NULL;\r
583}\r
584\r
585static PyMethodDef poll_methods[] = {\r
586 {"register", (PyCFunction)poll_register,\r
587 METH_VARARGS, poll_register_doc},\r
588 {"modify", (PyCFunction)poll_modify,\r
589 METH_VARARGS, poll_modify_doc},\r
590 {"unregister", (PyCFunction)poll_unregister,\r
591 METH_O, poll_unregister_doc},\r
592 {"poll", (PyCFunction)poll_poll,\r
593 METH_VARARGS, poll_poll_doc},\r
594 {NULL, NULL} /* sentinel */\r
595};\r
596\r
597static pollObject *\r
598newPollObject(void)\r
599{\r
600 pollObject *self;\r
601 self = PyObject_New(pollObject, &poll_Type);\r
602 if (self == NULL)\r
603 return NULL;\r
604 /* ufd_uptodate is a Boolean, denoting whether the\r
605 array pointed to by ufds matches the contents of the dictionary. */\r
606 self->ufd_uptodate = 0;\r
607 self->ufds = NULL;\r
608 self->dict = PyDict_New();\r
609 if (self->dict == NULL) {\r
610 Py_DECREF(self);\r
611 return NULL;\r
612 }\r
613 return self;\r
614}\r
615\r
616static void\r
617poll_dealloc(pollObject *self)\r
618{\r
619 if (self->ufds != NULL)\r
620 PyMem_DEL(self->ufds);\r
621 Py_XDECREF(self->dict);\r
622 PyObject_Del(self);\r
623}\r
624\r
625static PyObject *\r
626poll_getattr(pollObject *self, char *name)\r
627{\r
628 return Py_FindMethod(poll_methods, (PyObject *)self, name);\r
629}\r
630\r
631static PyTypeObject poll_Type = {\r
632 /* The ob_type field must be initialized in the module init function\r
633 * to be portable to Windows without using C++. */\r
634 PyVarObject_HEAD_INIT(NULL, 0)\r
635 "select.poll", /*tp_name*/\r
636 sizeof(pollObject), /*tp_basicsize*/\r
637 0, /*tp_itemsize*/\r
638 /* methods */\r
639 (destructor)poll_dealloc, /*tp_dealloc*/\r
640 0, /*tp_print*/\r
641 (getattrfunc)poll_getattr, /*tp_getattr*/\r
642 0, /*tp_setattr*/\r
643 0, /*tp_compare*/\r
644 0, /*tp_repr*/\r
645 0, /*tp_as_number*/\r
646 0, /*tp_as_sequence*/\r
647 0, /*tp_as_mapping*/\r
648 0, /*tp_hash*/\r
649};\r
650\r
651PyDoc_STRVAR(poll_doc,\r
652"Returns a polling object, which supports registering and\n\\r
653unregistering file descriptors, and then polling them for I/O events.");\r
654\r
655static PyObject *\r
656select_poll(PyObject *self, PyObject *unused)\r
657{\r
658 return (PyObject *)newPollObject();\r
659}\r
660\r
661#ifdef __APPLE__\r
662/*\r
663 * On some systems poll() sets errno on invalid file descriptors. We test\r
664 * for this at runtime because this bug may be fixed or introduced between\r
665 * OS releases.\r
666 */\r
667static int select_have_broken_poll(void)\r
668{\r
669 int poll_test;\r
670 int filedes[2];\r
671\r
672 struct pollfd poll_struct = { 0, POLLIN|POLLPRI|POLLOUT, 0 };\r
673\r
674 /* Create a file descriptor to make invalid */\r
675 if (pipe(filedes) < 0) {\r
676 return 1;\r
677 }\r
678 poll_struct.fd = filedes[0];\r
679 close(filedes[0]);\r
680 close(filedes[1]);\r
681 poll_test = poll(&poll_struct, 1, 0);\r
682 if (poll_test < 0) {\r
683 return 1;\r
684 } else if (poll_test == 0 && poll_struct.revents != POLLNVAL) {\r
685 return 1;\r
686 }\r
687 return 0;\r
688}\r
689#endif /* __APPLE__ */\r
690\r
691#endif /* HAVE_POLL */\r
692\r
693#ifdef HAVE_EPOLL\r
694/* **************************************************************************\r
695 * epoll interface for Linux 2.6\r
696 *\r
697 * Written by Christian Heimes\r
698 * Inspired by Twisted's _epoll.pyx and select.poll()\r
699 */\r
700\r
701#ifdef HAVE_SYS_EPOLL_H\r
702#include <sys/epoll.h>\r
703#endif\r
704\r
705typedef struct {\r
706 PyObject_HEAD\r
707 SOCKET epfd; /* epoll control file descriptor */\r
708} pyEpoll_Object;\r
709\r
710static PyTypeObject pyEpoll_Type;\r
711#define pyepoll_CHECK(op) (PyObject_TypeCheck((op), &pyEpoll_Type))\r
712\r
713static PyObject *\r
714pyepoll_err_closed(void)\r
715{\r
716 PyErr_SetString(PyExc_ValueError, "I/O operation on closed epoll fd");\r
717 return NULL;\r
718}\r
719\r
720static int\r
721pyepoll_internal_close(pyEpoll_Object *self)\r
722{\r
723 int save_errno = 0;\r
724 if (self->epfd >= 0) {\r
725 int epfd = self->epfd;\r
726 self->epfd = -1;\r
727 Py_BEGIN_ALLOW_THREADS\r
728 if (close(epfd) < 0)\r
729 save_errno = errno;\r
730 Py_END_ALLOW_THREADS\r
731 }\r
732 return save_errno;\r
733}\r
734\r
735static PyObject *\r
736newPyEpoll_Object(PyTypeObject *type, int sizehint, SOCKET fd)\r
737{\r
738 pyEpoll_Object *self;\r
739\r
740 if (sizehint == -1) {\r
741 sizehint = FD_SETSIZE-1;\r
742 }\r
743 else if (sizehint < 1) {\r
744 PyErr_Format(PyExc_ValueError,\r
745 "sizehint must be greater zero, got %d",\r
746 sizehint);\r
747 return NULL;\r
748 }\r
749\r
750 assert(type != NULL && type->tp_alloc != NULL);\r
751 self = (pyEpoll_Object *) type->tp_alloc(type, 0);\r
752 if (self == NULL)\r
753 return NULL;\r
754\r
755 if (fd == -1) {\r
756 Py_BEGIN_ALLOW_THREADS\r
757 self->epfd = epoll_create(sizehint);\r
758 Py_END_ALLOW_THREADS\r
759 }\r
760 else {\r
761 self->epfd = fd;\r
762 }\r
763 if (self->epfd < 0) {\r
764 Py_DECREF(self);\r
765 PyErr_SetFromErrno(PyExc_IOError);\r
766 return NULL;\r
767 }\r
768 return (PyObject *)self;\r
769}\r
770\r
771\r
772static PyObject *\r
773pyepoll_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
774{\r
775 int sizehint = -1;\r
776 static char *kwlist[] = {"sizehint", NULL};\r
777\r
778 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i:epoll", kwlist,\r
779 &sizehint))\r
780 return NULL;\r
781\r
782 return newPyEpoll_Object(type, sizehint, -1);\r
783}\r
784\r
785\r
786static void\r
787pyepoll_dealloc(pyEpoll_Object *self)\r
788{\r
789 (void)pyepoll_internal_close(self);\r
790 Py_TYPE(self)->tp_free(self);\r
791}\r
792\r
793static PyObject*\r
794pyepoll_close(pyEpoll_Object *self)\r
795{\r
796 errno = pyepoll_internal_close(self);\r
797 if (errno < 0) {\r
798 PyErr_SetFromErrno(PyExc_IOError);\r
799 return NULL;\r
800 }\r
801 Py_RETURN_NONE;\r
802}\r
803\r
804PyDoc_STRVAR(pyepoll_close_doc,\r
805"close() -> None\n\\r
806\n\\r
807Close the epoll control file descriptor. Further operations on the epoll\n\\r
808object will raise an exception.");\r
809\r
810static PyObject*\r
811pyepoll_get_closed(pyEpoll_Object *self)\r
812{\r
813 if (self->epfd < 0)\r
814 Py_RETURN_TRUE;\r
815 else\r
816 Py_RETURN_FALSE;\r
817}\r
818\r
819static PyObject*\r
820pyepoll_fileno(pyEpoll_Object *self)\r
821{\r
822 if (self->epfd < 0)\r
823 return pyepoll_err_closed();\r
824 return PyInt_FromLong(self->epfd);\r
825}\r
826\r
827PyDoc_STRVAR(pyepoll_fileno_doc,\r
828"fileno() -> int\n\\r
829\n\\r
830Return the epoll control file descriptor.");\r
831\r
832static PyObject*\r
833pyepoll_fromfd(PyObject *cls, PyObject *args)\r
834{\r
835 SOCKET fd;\r
836\r
837 if (!PyArg_ParseTuple(args, "i:fromfd", &fd))\r
838 return NULL;\r
839\r
840 return newPyEpoll_Object((PyTypeObject*)cls, -1, fd);\r
841}\r
842\r
843PyDoc_STRVAR(pyepoll_fromfd_doc,\r
844"fromfd(fd) -> epoll\n\\r
845\n\\r
846Create an epoll object from a given control fd.");\r
847\r
848static PyObject *\r
849pyepoll_internal_ctl(int epfd, int op, PyObject *pfd, unsigned int events)\r
850{\r
851 struct epoll_event ev;\r
852 int result;\r
853 int fd;\r
854\r
855 if (epfd < 0)\r
856 return pyepoll_err_closed();\r
857\r
858 fd = PyObject_AsFileDescriptor(pfd);\r
859 if (fd == -1) {\r
860 return NULL;\r
861 }\r
862\r
863 switch(op) {\r
864 case EPOLL_CTL_ADD:\r
865 case EPOLL_CTL_MOD:\r
866 ev.events = events;\r
867 ev.data.fd = fd;\r
868 Py_BEGIN_ALLOW_THREADS\r
869 result = epoll_ctl(epfd, op, fd, &ev);\r
870 Py_END_ALLOW_THREADS\r
871 break;\r
872 case EPOLL_CTL_DEL:\r
873 /* In kernel versions before 2.6.9, the EPOLL_CTL_DEL\r
874 * operation required a non-NULL pointer in event, even\r
875 * though this argument is ignored. */\r
876 Py_BEGIN_ALLOW_THREADS\r
877 result = epoll_ctl(epfd, op, fd, &ev);\r
878 if (errno == EBADF) {\r
879 /* fd already closed */\r
880 result = 0;\r
881 errno = 0;\r
882 }\r
883 Py_END_ALLOW_THREADS\r
884 break;\r
885 default:\r
886 result = -1;\r
887 errno = EINVAL;\r
888 }\r
889\r
890 if (result < 0) {\r
891 PyErr_SetFromErrno(PyExc_IOError);\r
892 return NULL;\r
893 }\r
894 Py_RETURN_NONE;\r
895}\r
896\r
897static PyObject *\r
898pyepoll_register(pyEpoll_Object *self, PyObject *args, PyObject *kwds)\r
899{\r
900 PyObject *pfd;\r
901 unsigned int events = EPOLLIN | EPOLLOUT | EPOLLPRI;\r
902 static char *kwlist[] = {"fd", "eventmask", NULL};\r
903\r
904 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|I:register", kwlist,\r
905 &pfd, &events)) {\r
906 return NULL;\r
907 }\r
908\r
909 return pyepoll_internal_ctl(self->epfd, EPOLL_CTL_ADD, pfd, events);\r
910}\r
911\r
912PyDoc_STRVAR(pyepoll_register_doc,\r
913"register(fd[, eventmask]) -> None\n\\r
914\n\\r
915Registers a new fd or modifies an already registered fd.\n\\r
916fd is the target file descriptor of the operation.\n\\r
917events is a bit set composed of the various EPOLL constants; the default\n\\r
918is EPOLL_IN | EPOLL_OUT | EPOLL_PRI.\n\\r
919\n\\r
920The epoll interface supports all file descriptors that support poll.");\r
921\r
922static PyObject *\r
923pyepoll_modify(pyEpoll_Object *self, PyObject *args, PyObject *kwds)\r
924{\r
925 PyObject *pfd;\r
926 unsigned int events;\r
927 static char *kwlist[] = {"fd", "eventmask", NULL};\r
928\r
929 if (!PyArg_ParseTupleAndKeywords(args, kwds, "OI:modify", kwlist,\r
930 &pfd, &events)) {\r
931 return NULL;\r
932 }\r
933\r
934 return pyepoll_internal_ctl(self->epfd, EPOLL_CTL_MOD, pfd, events);\r
935}\r
936\r
937PyDoc_STRVAR(pyepoll_modify_doc,\r
938"modify(fd, eventmask) -> None\n\\r
939\n\\r
940fd is the target file descriptor of the operation\n\\r
941events is a bit set composed of the various EPOLL constants");\r
942\r
943static PyObject *\r
944pyepoll_unregister(pyEpoll_Object *self, PyObject *args, PyObject *kwds)\r
945{\r
946 PyObject *pfd;\r
947 static char *kwlist[] = {"fd", NULL};\r
948\r
949 if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:unregister", kwlist,\r
950 &pfd)) {\r
951 return NULL;\r
952 }\r
953\r
954 return pyepoll_internal_ctl(self->epfd, EPOLL_CTL_DEL, pfd, 0);\r
955}\r
956\r
957PyDoc_STRVAR(pyepoll_unregister_doc,\r
958"unregister(fd) -> None\n\\r
959\n\\r
960fd is the target file descriptor of the operation.");\r
961\r
962static PyObject *\r
963pyepoll_poll(pyEpoll_Object *self, PyObject *args, PyObject *kwds)\r
964{\r
965 double dtimeout = -1.;\r
966 int timeout;\r
967 int maxevents = -1;\r
968 int nfds, i;\r
969 PyObject *elist = NULL, *etuple = NULL;\r
970 struct epoll_event *evs = NULL;\r
971 static char *kwlist[] = {"timeout", "maxevents", NULL};\r
972\r
973 if (self->epfd < 0)\r
974 return pyepoll_err_closed();\r
975\r
976 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|di:poll", kwlist,\r
977 &dtimeout, &maxevents)) {\r
978 return NULL;\r
979 }\r
980\r
981 if (dtimeout < 0) {\r
982 timeout = -1;\r
983 }\r
984 else if (dtimeout * 1000.0 > INT_MAX) {\r
985 PyErr_SetString(PyExc_OverflowError,\r
986 "timeout is too large");\r
987 return NULL;\r
988 }\r
989 else {\r
990 timeout = (int)(dtimeout * 1000.0);\r
991 }\r
992\r
993 if (maxevents == -1) {\r
994 maxevents = FD_SETSIZE-1;\r
995 }\r
996 else if (maxevents < 1) {\r
997 PyErr_Format(PyExc_ValueError,\r
998 "maxevents must be greater than 0, got %d",\r
999 maxevents);\r
1000 return NULL;\r
1001 }\r
1002\r
1003 evs = PyMem_New(struct epoll_event, maxevents);\r
1004 if (evs == NULL) {\r
1005 Py_DECREF(self);\r
1006 PyErr_NoMemory();\r
1007 return NULL;\r
1008 }\r
1009\r
1010 Py_BEGIN_ALLOW_THREADS\r
1011 nfds = epoll_wait(self->epfd, evs, maxevents, timeout);\r
1012 Py_END_ALLOW_THREADS\r
1013 if (nfds < 0) {\r
1014 PyErr_SetFromErrno(PyExc_IOError);\r
1015 goto error;\r
1016 }\r
1017\r
1018 elist = PyList_New(nfds);\r
1019 if (elist == NULL) {\r
1020 goto error;\r
1021 }\r
1022\r
1023 for (i = 0; i < nfds; i++) {\r
1024 etuple = Py_BuildValue("iI", evs[i].data.fd, evs[i].events);\r
1025 if (etuple == NULL) {\r
1026 Py_CLEAR(elist);\r
1027 goto error;\r
1028 }\r
1029 PyList_SET_ITEM(elist, i, etuple);\r
1030 }\r
1031\r
1032 error:\r
1033 PyMem_Free(evs);\r
1034 return elist;\r
1035}\r
1036\r
1037PyDoc_STRVAR(pyepoll_poll_doc,\r
1038"poll([timeout=-1[, maxevents=-1]]) -> [(fd, events), (...)]\n\\r
1039\n\\r
1040Wait for events on the epoll file descriptor for a maximum time of timeout\n\\r
1041in seconds (as float). -1 makes poll wait indefinitely.\n\\r
1042Up to maxevents are returned to the caller.");\r
1043\r
1044static PyMethodDef pyepoll_methods[] = {\r
1045 {"fromfd", (PyCFunction)pyepoll_fromfd,\r
1046 METH_VARARGS | METH_CLASS, pyepoll_fromfd_doc},\r
1047 {"close", (PyCFunction)pyepoll_close, METH_NOARGS,\r
1048 pyepoll_close_doc},\r
1049 {"fileno", (PyCFunction)pyepoll_fileno, METH_NOARGS,\r
1050 pyepoll_fileno_doc},\r
1051 {"modify", (PyCFunction)pyepoll_modify,\r
1052 METH_VARARGS | METH_KEYWORDS, pyepoll_modify_doc},\r
1053 {"register", (PyCFunction)pyepoll_register,\r
1054 METH_VARARGS | METH_KEYWORDS, pyepoll_register_doc},\r
1055 {"unregister", (PyCFunction)pyepoll_unregister,\r
1056 METH_VARARGS | METH_KEYWORDS, pyepoll_unregister_doc},\r
1057 {"poll", (PyCFunction)pyepoll_poll,\r
1058 METH_VARARGS | METH_KEYWORDS, pyepoll_poll_doc},\r
1059 {NULL, NULL},\r
1060};\r
1061\r
1062static PyGetSetDef pyepoll_getsetlist[] = {\r
1063 {"closed", (getter)pyepoll_get_closed, NULL,\r
1064 "True if the epoll handler is closed"},\r
1065 {0},\r
1066};\r
1067\r
1068PyDoc_STRVAR(pyepoll_doc,\r
1069"select.epoll([sizehint=-1])\n\\r
1070\n\\r
1071Returns an epolling object\n\\r
1072\n\\r
1073sizehint must be a positive integer or -1 for the default size. The\n\\r
1074sizehint is used to optimize internal data structures. It doesn't limit\n\\r
1075the maximum number of monitored events.");\r
1076\r
1077static PyTypeObject pyEpoll_Type = {\r
1078 PyVarObject_HEAD_INIT(NULL, 0)\r
1079 "select.epoll", /* tp_name */\r
1080 sizeof(pyEpoll_Object), /* tp_basicsize */\r
1081 0, /* tp_itemsize */\r
1082 (destructor)pyepoll_dealloc, /* tp_dealloc */\r
1083 0, /* tp_print */\r
1084 0, /* tp_getattr */\r
1085 0, /* tp_setattr */\r
1086 0, /* tp_compare */\r
1087 0, /* tp_repr */\r
1088 0, /* tp_as_number */\r
1089 0, /* tp_as_sequence */\r
1090 0, /* tp_as_mapping */\r
1091 0, /* tp_hash */\r
1092 0, /* tp_call */\r
1093 0, /* tp_str */\r
1094 PyObject_GenericGetAttr, /* tp_getattro */\r
1095 0, /* tp_setattro */\r
1096 0, /* tp_as_buffer */\r
1097 Py_TPFLAGS_DEFAULT, /* tp_flags */\r
1098 pyepoll_doc, /* tp_doc */\r
1099 0, /* tp_traverse */\r
1100 0, /* tp_clear */\r
1101 0, /* tp_richcompare */\r
1102 0, /* tp_weaklistoffset */\r
1103 0, /* tp_iter */\r
1104 0, /* tp_iternext */\r
1105 pyepoll_methods, /* tp_methods */\r
1106 0, /* tp_members */\r
1107 pyepoll_getsetlist, /* tp_getset */\r
1108 0, /* tp_base */\r
1109 0, /* tp_dict */\r
1110 0, /* tp_descr_get */\r
1111 0, /* tp_descr_set */\r
1112 0, /* tp_dictoffset */\r
1113 0, /* tp_init */\r
1114 0, /* tp_alloc */\r
1115 pyepoll_new, /* tp_new */\r
1116 0, /* tp_free */\r
1117};\r
1118\r
1119#endif /* HAVE_EPOLL */\r
1120\r
1121#ifdef HAVE_KQUEUE\r
1122/* **************************************************************************\r
1123 * kqueue interface for BSD\r
1124 *\r
1125 * Copyright (c) 2000 Doug White, 2006 James Knight, 2007 Christian Heimes\r
1126 * All rights reserved.\r
1127 *\r
1128 * Redistribution and use in source and binary forms, with or without\r
1129 * modification, are permitted provided that the following conditions\r
1130 * are met:\r
1131 * 1. Redistributions of source code must retain the above copyright\r
1132 * notice, this list of conditions and the following disclaimer.\r
1133 * 2. Redistributions in binary form must reproduce the above copyright\r
1134 * notice, this list of conditions and the following disclaimer in the\r
1135 * documentation and/or other materials provided with the distribution.\r
1136 *\r
1137 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND\r
1138 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
1139 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
1140 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\r
1141 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
1142 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
1143 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
1144 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\r
1145 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\r
1146 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\r
1147 * SUCH DAMAGE.\r
1148 */\r
1149\r
1150#ifdef HAVE_SYS_EVENT_H\r
1151#include <sys/event.h>\r
1152#endif\r
1153\r
1154PyDoc_STRVAR(kqueue_event_doc,\r
1155"kevent(ident, filter=KQ_FILTER_READ, flags=KQ_EV_ADD, fflags=0, data=0, udata=0)\n\\r
1156\n\\r
1157This object is the equivalent of the struct kevent for the C API.\n\\r
1158\n\\r
1159See the kqueue manpage for more detailed information about the meaning\n\\r
1160of the arguments.\n\\r
1161\n\\r
1162One minor note: while you might hope that udata could store a\n\\r
1163reference to a python object, it cannot, because it is impossible to\n\\r
1164keep a proper reference count of the object once it's passed into the\n\\r
1165kernel. Therefore, I have restricted it to only storing an integer. I\n\\r
1166recommend ignoring it and simply using the 'ident' field to key off\n\\r
1167of. You could also set up a dictionary on the python side to store a\n\\r
1168udata->object mapping.");\r
1169\r
1170typedef struct {\r
1171 PyObject_HEAD\r
1172 struct kevent e;\r
1173} kqueue_event_Object;\r
1174\r
1175static PyTypeObject kqueue_event_Type;\r
1176\r
1177#define kqueue_event_Check(op) (PyObject_TypeCheck((op), &kqueue_event_Type))\r
1178\r
1179typedef struct {\r
1180 PyObject_HEAD\r
1181 SOCKET kqfd; /* kqueue control fd */\r
1182} kqueue_queue_Object;\r
1183\r
1184static PyTypeObject kqueue_queue_Type;\r
1185\r
1186#define kqueue_queue_Check(op) (PyObject_TypeCheck((op), &kqueue_queue_Type))\r
1187\r
1188#if (SIZEOF_UINTPTR_T != SIZEOF_VOID_P)\r
1189# error uintptr_t does not match void *!\r
1190#elif (SIZEOF_UINTPTR_T == SIZEOF_LONG_LONG)\r
1191# define T_UINTPTRT T_ULONGLONG\r
1192# define T_INTPTRT T_LONGLONG\r
1193# define PyLong_AsUintptr_t PyLong_AsUnsignedLongLong\r
1194# define UINTPTRT_FMT_UNIT "K"\r
1195# define INTPTRT_FMT_UNIT "L"\r
1196#elif (SIZEOF_UINTPTR_T == SIZEOF_LONG)\r
1197# define T_UINTPTRT T_ULONG\r
1198# define T_INTPTRT T_LONG\r
1199# define PyLong_AsUintptr_t PyLong_AsUnsignedLong\r
1200# define UINTPTRT_FMT_UNIT "k"\r
1201# define INTPTRT_FMT_UNIT "l"\r
1202#elif (SIZEOF_UINTPTR_T == SIZEOF_INT)\r
1203# define T_UINTPTRT T_UINT\r
1204# define T_INTPTRT T_INT\r
1205# define PyLong_AsUintptr_t PyLong_AsUnsignedLong\r
1206# define UINTPTRT_FMT_UNIT "I"\r
1207# define INTPTRT_FMT_UNIT "i"\r
1208#else\r
1209# error uintptr_t does not match int, long, or long long!\r
1210#endif\r
1211\r
1212/* Unfortunately, we can't store python objects in udata, because\r
1213 * kevents in the kernel can be removed without warning, which would\r
1214 * forever lose the refcount on the object stored with it.\r
1215 */\r
1216\r
1217#define KQ_OFF(x) offsetof(kqueue_event_Object, x)\r
1218static struct PyMemberDef kqueue_event_members[] = {\r
1219 {"ident", T_UINTPTRT, KQ_OFF(e.ident)},\r
1220 {"filter", T_SHORT, KQ_OFF(e.filter)},\r
1221 {"flags", T_USHORT, KQ_OFF(e.flags)},\r
1222 {"fflags", T_UINT, KQ_OFF(e.fflags)},\r
1223 {"data", T_INTPTRT, KQ_OFF(e.data)},\r
1224 {"udata", T_UINTPTRT, KQ_OFF(e.udata)},\r
1225 {NULL} /* Sentinel */\r
1226};\r
1227#undef KQ_OFF\r
1228\r
1229static PyObject *\r
1230\r
1231kqueue_event_repr(kqueue_event_Object *s)\r
1232{\r
1233 char buf[1024];\r
1234 PyOS_snprintf(\r
1235 buf, sizeof(buf),\r
1236 "<select.kevent ident=%zu filter=%d flags=0x%x fflags=0x%x "\r
1237 "data=0x%zd udata=%p>",\r
1238 (size_t)(s->e.ident), s->e.filter, s->e.flags,\r
1239 s->e.fflags, (Py_ssize_t)(s->e.data), s->e.udata);\r
1240 return PyString_FromString(buf);\r
1241}\r
1242\r
1243static int\r
1244kqueue_event_init(kqueue_event_Object *self, PyObject *args, PyObject *kwds)\r
1245{\r
1246 PyObject *pfd;\r
1247 static char *kwlist[] = {"ident", "filter", "flags", "fflags",\r
1248 "data", "udata", NULL};\r
1249 static char *fmt = "O|hhi" INTPTRT_FMT_UNIT UINTPTRT_FMT_UNIT ":kevent";\r
1250\r
1251 EV_SET(&(self->e), 0, EVFILT_READ, EV_ADD, 0, 0, 0); /* defaults */\r
1252\r
1253 if (!PyArg_ParseTupleAndKeywords(args, kwds, fmt, kwlist,\r
1254 &pfd, &(self->e.filter), &(self->e.flags),\r
1255 &(self->e.fflags), &(self->e.data), &(self->e.udata))) {\r
1256 return -1;\r
1257 }\r
1258\r
1259 if (PyLong_Check(pfd)) {\r
1260 self->e.ident = PyLong_AsUintptr_t(pfd);\r
1261 }\r
1262 else {\r
1263 self->e.ident = PyObject_AsFileDescriptor(pfd);\r
1264 }\r
1265 if (PyErr_Occurred()) {\r
1266 return -1;\r
1267 }\r
1268 return 0;\r
1269}\r
1270\r
1271static PyObject *\r
1272kqueue_event_richcompare(kqueue_event_Object *s, kqueue_event_Object *o,\r
1273 int op)\r
1274{\r
1275 Py_intptr_t result = 0;\r
1276\r
1277 if (!kqueue_event_Check(o)) {\r
1278 if (op == Py_EQ || op == Py_NE) {\r
1279 PyObject *res = op == Py_EQ ? Py_False : Py_True;\r
1280 Py_INCREF(res);\r
1281 return res;\r
1282 }\r
1283 PyErr_Format(PyExc_TypeError,\r
1284 "can't compare %.200s to %.200s",\r
1285 Py_TYPE(s)->tp_name, Py_TYPE(o)->tp_name);\r
1286 return NULL;\r
1287 }\r
1288 if (((result = s->e.ident - o->e.ident) == 0) &&\r
1289 ((result = s->e.filter - o->e.filter) == 0) &&\r
1290 ((result = s->e.flags - o->e.flags) == 0) &&\r
1291 ((result = s->e.fflags - o->e.fflags) == 0) &&\r
1292 ((result = s->e.data - o->e.data) == 0) &&\r
1293 ((result = s->e.udata - o->e.udata) == 0)\r
1294 ) {\r
1295 result = 0;\r
1296 }\r
1297\r
1298 switch (op) {\r
1299 case Py_EQ:\r
1300 result = (result == 0);\r
1301 break;\r
1302 case Py_NE:\r
1303 result = (result != 0);\r
1304 break;\r
1305 case Py_LE:\r
1306 result = (result <= 0);\r
1307 break;\r
1308 case Py_GE:\r
1309 result = (result >= 0);\r
1310 break;\r
1311 case Py_LT:\r
1312 result = (result < 0);\r
1313 break;\r
1314 case Py_GT:\r
1315 result = (result > 0);\r
1316 break;\r
1317 }\r
1318 return PyBool_FromLong((long)result);\r
1319}\r
1320\r
1321static PyTypeObject kqueue_event_Type = {\r
1322 PyVarObject_HEAD_INIT(NULL, 0)\r
1323 "select.kevent", /* tp_name */\r
1324 sizeof(kqueue_event_Object), /* tp_basicsize */\r
1325 0, /* tp_itemsize */\r
1326 0, /* tp_dealloc */\r
1327 0, /* tp_print */\r
1328 0, /* tp_getattr */\r
1329 0, /* tp_setattr */\r
1330 0, /* tp_compare */\r
1331 (reprfunc)kqueue_event_repr, /* tp_repr */\r
1332 0, /* tp_as_number */\r
1333 0, /* tp_as_sequence */\r
1334 0, /* tp_as_mapping */\r
1335 0, /* tp_hash */\r
1336 0, /* tp_call */\r
1337 0, /* tp_str */\r
1338 0, /* tp_getattro */\r
1339 0, /* tp_setattro */\r
1340 0, /* tp_as_buffer */\r
1341 Py_TPFLAGS_DEFAULT, /* tp_flags */\r
1342 kqueue_event_doc, /* tp_doc */\r
1343 0, /* tp_traverse */\r
1344 0, /* tp_clear */\r
1345 (richcmpfunc)kqueue_event_richcompare, /* tp_richcompare */\r
1346 0, /* tp_weaklistoffset */\r
1347 0, /* tp_iter */\r
1348 0, /* tp_iternext */\r
1349 0, /* tp_methods */\r
1350 kqueue_event_members, /* tp_members */\r
1351 0, /* tp_getset */\r
1352 0, /* tp_base */\r
1353 0, /* tp_dict */\r
1354 0, /* tp_descr_get */\r
1355 0, /* tp_descr_set */\r
1356 0, /* tp_dictoffset */\r
1357 (initproc)kqueue_event_init, /* tp_init */\r
1358 0, /* tp_alloc */\r
1359 0, /* tp_new */\r
1360 0, /* tp_free */\r
1361};\r
1362\r
1363static PyObject *\r
1364kqueue_queue_err_closed(void)\r
1365{\r
1366 PyErr_SetString(PyExc_ValueError, "I/O operation on closed kqueue fd");\r
1367 return NULL;\r
1368}\r
1369\r
1370static int\r
1371kqueue_queue_internal_close(kqueue_queue_Object *self)\r
1372{\r
1373 int save_errno = 0;\r
1374 if (self->kqfd >= 0) {\r
1375 int kqfd = self->kqfd;\r
1376 self->kqfd = -1;\r
1377 Py_BEGIN_ALLOW_THREADS\r
1378 if (close(kqfd) < 0)\r
1379 save_errno = errno;\r
1380 Py_END_ALLOW_THREADS\r
1381 }\r
1382 return save_errno;\r
1383}\r
1384\r
1385static PyObject *\r
1386newKqueue_Object(PyTypeObject *type, SOCKET fd)\r
1387{\r
1388 kqueue_queue_Object *self;\r
1389 assert(type != NULL && type->tp_alloc != NULL);\r
1390 self = (kqueue_queue_Object *) type->tp_alloc(type, 0);\r
1391 if (self == NULL) {\r
1392 return NULL;\r
1393 }\r
1394\r
1395 if (fd == -1) {\r
1396 Py_BEGIN_ALLOW_THREADS\r
1397 self->kqfd = kqueue();\r
1398 Py_END_ALLOW_THREADS\r
1399 }\r
1400 else {\r
1401 self->kqfd = fd;\r
1402 }\r
1403 if (self->kqfd < 0) {\r
1404 Py_DECREF(self);\r
1405 PyErr_SetFromErrno(PyExc_IOError);\r
1406 return NULL;\r
1407 }\r
1408 return (PyObject *)self;\r
1409}\r
1410\r
1411static PyObject *\r
1412kqueue_queue_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
1413{\r
1414\r
1415 if ((args != NULL && PyObject_Size(args)) ||\r
1416 (kwds != NULL && PyObject_Size(kwds))) {\r
1417 PyErr_SetString(PyExc_ValueError,\r
1418 "select.kqueue doesn't accept arguments");\r
1419 return NULL;\r
1420 }\r
1421\r
1422 return newKqueue_Object(type, -1);\r
1423}\r
1424\r
1425static void\r
1426kqueue_queue_dealloc(kqueue_queue_Object *self)\r
1427{\r
1428 kqueue_queue_internal_close(self);\r
1429 Py_TYPE(self)->tp_free(self);\r
1430}\r
1431\r
1432static PyObject*\r
1433kqueue_queue_close(kqueue_queue_Object *self)\r
1434{\r
1435 errno = kqueue_queue_internal_close(self);\r
1436 if (errno < 0) {\r
1437 PyErr_SetFromErrno(PyExc_IOError);\r
1438 return NULL;\r
1439 }\r
1440 Py_RETURN_NONE;\r
1441}\r
1442\r
1443PyDoc_STRVAR(kqueue_queue_close_doc,\r
1444"close() -> None\n\\r
1445\n\\r
1446Close the kqueue control file descriptor. Further operations on the kqueue\n\\r
1447object will raise an exception.");\r
1448\r
1449static PyObject*\r
1450kqueue_queue_get_closed(kqueue_queue_Object *self)\r
1451{\r
1452 if (self->kqfd < 0)\r
1453 Py_RETURN_TRUE;\r
1454 else\r
1455 Py_RETURN_FALSE;\r
1456}\r
1457\r
1458static PyObject*\r
1459kqueue_queue_fileno(kqueue_queue_Object *self)\r
1460{\r
1461 if (self->kqfd < 0)\r
1462 return kqueue_queue_err_closed();\r
1463 return PyInt_FromLong(self->kqfd);\r
1464}\r
1465\r
1466PyDoc_STRVAR(kqueue_queue_fileno_doc,\r
1467"fileno() -> int\n\\r
1468\n\\r
1469Return the kqueue control file descriptor.");\r
1470\r
1471static PyObject*\r
1472kqueue_queue_fromfd(PyObject *cls, PyObject *args)\r
1473{\r
1474 SOCKET fd;\r
1475\r
1476 if (!PyArg_ParseTuple(args, "i:fromfd", &fd))\r
1477 return NULL;\r
1478\r
1479 return newKqueue_Object((PyTypeObject*)cls, fd);\r
1480}\r
1481\r
1482PyDoc_STRVAR(kqueue_queue_fromfd_doc,\r
1483"fromfd(fd) -> kqueue\n\\r
1484\n\\r
1485Create a kqueue object from a given control fd.");\r
1486\r
1487static PyObject *\r
1488kqueue_queue_control(kqueue_queue_Object *self, PyObject *args)\r
1489{\r
1490 int nevents = 0;\r
1491 int gotevents = 0;\r
1492 int nchanges = 0;\r
1493 int i = 0;\r
1494 PyObject *otimeout = NULL;\r
1495 PyObject *ch = NULL;\r
1496 PyObject *it = NULL, *ei = NULL;\r
1497 PyObject *result = NULL;\r
1498 struct kevent *evl = NULL;\r
1499 struct kevent *chl = NULL;\r
1500 struct timespec timeoutspec;\r
1501 struct timespec *ptimeoutspec;\r
1502\r
1503 if (self->kqfd < 0)\r
1504 return kqueue_queue_err_closed();\r
1505\r
1506 if (!PyArg_ParseTuple(args, "Oi|O:control", &ch, &nevents, &otimeout))\r
1507 return NULL;\r
1508\r
1509 if (nevents < 0) {\r
1510 PyErr_Format(PyExc_ValueError,\r
1511 "Length of eventlist must be 0 or positive, got %d",\r
1512 nevents);\r
1513 return NULL;\r
1514 }\r
1515\r
1516 if (otimeout == Py_None || otimeout == NULL) {\r
1517 ptimeoutspec = NULL;\r
1518 }\r
1519 else if (PyNumber_Check(otimeout)) {\r
1520 double timeout;\r
1521 long seconds;\r
1522\r
1523 timeout = PyFloat_AsDouble(otimeout);\r
1524 if (timeout == -1 && PyErr_Occurred())\r
1525 return NULL;\r
1526 if (timeout > (double)LONG_MAX) {\r
1527 PyErr_SetString(PyExc_OverflowError,\r
1528 "timeout period too long");\r
1529 return NULL;\r
1530 }\r
1531 if (timeout < 0) {\r
1532 PyErr_SetString(PyExc_ValueError,\r
1533 "timeout must be positive or None");\r
1534 return NULL;\r
1535 }\r
1536\r
1537 seconds = (long)timeout;\r
1538 timeout = timeout - (double)seconds;\r
1539 timeoutspec.tv_sec = seconds;\r
1540 timeoutspec.tv_nsec = (long)(timeout * 1E9);\r
1541 ptimeoutspec = &timeoutspec;\r
1542 }\r
1543 else {\r
1544 PyErr_Format(PyExc_TypeError,\r
1545 "timeout argument must be an number "\r
1546 "or None, got %.200s",\r
1547 Py_TYPE(otimeout)->tp_name);\r
1548 return NULL;\r
1549 }\r
1550\r
1551 if (ch != NULL && ch != Py_None) {\r
1552 it = PyObject_GetIter(ch);\r
1553 if (it == NULL) {\r
1554 PyErr_SetString(PyExc_TypeError,\r
1555 "changelist is not iterable");\r
1556 return NULL;\r
1557 }\r
1558 nchanges = PyObject_Size(ch);\r
1559 if (nchanges < 0) {\r
1560 goto error;\r
1561 }\r
1562\r
1563 chl = PyMem_New(struct kevent, nchanges);\r
1564 if (chl == NULL) {\r
1565 PyErr_NoMemory();\r
1566 goto error;\r
1567 }\r
1568 i = 0;\r
1569 while ((ei = PyIter_Next(it)) != NULL) {\r
1570 if (!kqueue_event_Check(ei)) {\r
1571 Py_DECREF(ei);\r
1572 PyErr_SetString(PyExc_TypeError,\r
1573 "changelist must be an iterable of "\r
1574 "select.kevent objects");\r
1575 goto error;\r
1576 } else {\r
1577 chl[i++] = ((kqueue_event_Object *)ei)->e;\r
1578 }\r
1579 Py_DECREF(ei);\r
1580 }\r
1581 }\r
1582 Py_CLEAR(it);\r
1583\r
1584 /* event list */\r
1585 if (nevents) {\r
1586 evl = PyMem_New(struct kevent, nevents);\r
1587 if (evl == NULL) {\r
1588 PyErr_NoMemory();\r
1589 goto error;\r
1590 }\r
1591 }\r
1592\r
1593 Py_BEGIN_ALLOW_THREADS\r
1594 gotevents = kevent(self->kqfd, chl, nchanges,\r
1595 evl, nevents, ptimeoutspec);\r
1596 Py_END_ALLOW_THREADS\r
1597\r
1598 if (gotevents == -1) {\r
1599 PyErr_SetFromErrno(PyExc_OSError);\r
1600 goto error;\r
1601 }\r
1602\r
1603 result = PyList_New(gotevents);\r
1604 if (result == NULL) {\r
1605 goto error;\r
1606 }\r
1607\r
1608 for (i = 0; i < gotevents; i++) {\r
1609 kqueue_event_Object *ch;\r
1610\r
1611 ch = PyObject_New(kqueue_event_Object, &kqueue_event_Type);\r
1612 if (ch == NULL) {\r
1613 goto error;\r
1614 }\r
1615 ch->e = evl[i];\r
1616 PyList_SET_ITEM(result, i, (PyObject *)ch);\r
1617 }\r
1618 PyMem_Free(chl);\r
1619 PyMem_Free(evl);\r
1620 return result;\r
1621\r
1622 error:\r
1623 PyMem_Free(chl);\r
1624 PyMem_Free(evl);\r
1625 Py_XDECREF(result);\r
1626 Py_XDECREF(it);\r
1627 return NULL;\r
1628}\r
1629\r
1630PyDoc_STRVAR(kqueue_queue_control_doc,\r
1631"control(changelist, max_events[, timeout=None]) -> eventlist\n\\r
1632\n\\r
1633Calls the kernel kevent function.\n\\r
1634- changelist must be a list of kevent objects describing the changes\n\\r
1635 to be made to the kernel's watch list or None.\n\\r
1636- max_events lets you specify the maximum number of events that the\n\\r
1637 kernel will return.\n\\r
1638- timeout is the maximum time to wait in seconds, or else None,\n\\r
1639 to wait forever. timeout accepts floats for smaller timeouts, too.");\r
1640\r
1641\r
1642static PyMethodDef kqueue_queue_methods[] = {\r
1643 {"fromfd", (PyCFunction)kqueue_queue_fromfd,\r
1644 METH_VARARGS | METH_CLASS, kqueue_queue_fromfd_doc},\r
1645 {"close", (PyCFunction)kqueue_queue_close, METH_NOARGS,\r
1646 kqueue_queue_close_doc},\r
1647 {"fileno", (PyCFunction)kqueue_queue_fileno, METH_NOARGS,\r
1648 kqueue_queue_fileno_doc},\r
1649 {"control", (PyCFunction)kqueue_queue_control,\r
1650 METH_VARARGS , kqueue_queue_control_doc},\r
1651 {NULL, NULL},\r
1652};\r
1653\r
1654static PyGetSetDef kqueue_queue_getsetlist[] = {\r
1655 {"closed", (getter)kqueue_queue_get_closed, NULL,\r
1656 "True if the kqueue handler is closed"},\r
1657 {0},\r
1658};\r
1659\r
1660PyDoc_STRVAR(kqueue_queue_doc,\r
1661"Kqueue syscall wrapper.\n\\r
1662\n\\r
1663For example, to start watching a socket for input:\n\\r
1664>>> kq = kqueue()\n\\r
1665>>> sock = socket()\n\\r
1666>>> sock.connect((host, port))\n\\r
1667>>> kq.control([kevent(sock, KQ_FILTER_WRITE, KQ_EV_ADD)], 0)\n\\r
1668\n\\r
1669To wait one second for it to become writeable:\n\\r
1670>>> kq.control(None, 1, 1000)\n\\r
1671\n\\r
1672To stop listening:\n\\r
1673>>> kq.control([kevent(sock, KQ_FILTER_WRITE, KQ_EV_DELETE)], 0)");\r
1674\r
1675static PyTypeObject kqueue_queue_Type = {\r
1676 PyVarObject_HEAD_INIT(NULL, 0)\r
1677 "select.kqueue", /* tp_name */\r
1678 sizeof(kqueue_queue_Object), /* tp_basicsize */\r
1679 0, /* tp_itemsize */\r
1680 (destructor)kqueue_queue_dealloc, /* tp_dealloc */\r
1681 0, /* tp_print */\r
1682 0, /* tp_getattr */\r
1683 0, /* tp_setattr */\r
1684 0, /* tp_compare */\r
1685 0, /* tp_repr */\r
1686 0, /* tp_as_number */\r
1687 0, /* tp_as_sequence */\r
1688 0, /* tp_as_mapping */\r
1689 0, /* tp_hash */\r
1690 0, /* tp_call */\r
1691 0, /* tp_str */\r
1692 0, /* tp_getattro */\r
1693 0, /* tp_setattro */\r
1694 0, /* tp_as_buffer */\r
1695 Py_TPFLAGS_DEFAULT, /* tp_flags */\r
1696 kqueue_queue_doc, /* tp_doc */\r
1697 0, /* tp_traverse */\r
1698 0, /* tp_clear */\r
1699 0, /* tp_richcompare */\r
1700 0, /* tp_weaklistoffset */\r
1701 0, /* tp_iter */\r
1702 0, /* tp_iternext */\r
1703 kqueue_queue_methods, /* tp_methods */\r
1704 0, /* tp_members */\r
1705 kqueue_queue_getsetlist, /* tp_getset */\r
1706 0, /* tp_base */\r
1707 0, /* tp_dict */\r
1708 0, /* tp_descr_get */\r
1709 0, /* tp_descr_set */\r
1710 0, /* tp_dictoffset */\r
1711 0, /* tp_init */\r
1712 0, /* tp_alloc */\r
1713 kqueue_queue_new, /* tp_new */\r
1714 0, /* tp_free */\r
1715};\r
1716\r
1717#endif /* HAVE_KQUEUE */\r
1718/* ************************************************************************ */\r
1719\r
1720PyDoc_STRVAR(select_doc,\r
1721"select(rlist, wlist, xlist[, timeout]) -> (rlist, wlist, xlist)\n\\r
1722\n\\r
1723Wait until one or more file descriptors are ready for some kind of I/O.\n\\r
1724The first three arguments are sequences of file descriptors to be waited for:\n\\r
1725rlist -- wait until ready for reading\n\\r
1726wlist -- wait until ready for writing\n\\r
1727xlist -- wait for an ``exceptional condition''\n\\r
1728If only one kind of condition is required, pass [] for the other lists.\n\\r
1729A file descriptor is either a socket or file object, or a small integer\n\\r
1730gotten from a fileno() method call on one of those.\n\\r
1731\n\\r
1732The optional 4th argument specifies a timeout in seconds; it may be\n\\r
1733a floating point number to specify fractions of seconds. If it is absent\n\\r
1734or None, the call will never time out.\n\\r
1735\n\\r
1736The return value is a tuple of three lists corresponding to the first three\n\\r
1737arguments; each contains the subset of the corresponding file descriptors\n\\r
1738that are ready.\n\\r
1739\n\\r
1740*** IMPORTANT NOTICE ***\n\\r
1741On Windows and OpenVMS, only sockets are supported; on Unix, all file\n\\r
1742descriptors can be used.");\r
1743\r
1744static PyMethodDef select_methods[] = {\r
1745 {"select", select_select, METH_VARARGS, select_doc},\r
1746#ifdef HAVE_POLL\r
1747 {"poll", select_poll, METH_NOARGS, poll_doc},\r
1748#endif /* HAVE_POLL */\r
1749 {0, 0}, /* sentinel */\r
1750};\r
1751\r
1752PyDoc_STRVAR(module_doc,\r
1753"This module supports asynchronous I/O on multiple file descriptors.\n\\r
1754\n\\r
1755*** IMPORTANT NOTICE ***\n\\r
1756On Windows and OpenVMS, only sockets are supported; on Unix, all file descriptors.");\r
1757\r
1758PyMODINIT_FUNC\r
1759initselect(void)\r
1760{\r
1761 PyObject *m;\r
1762 m = Py_InitModule3("select", select_methods, module_doc);\r
1763 if (m == NULL)\r
1764 return;\r
1765\r
1766 SelectError = PyErr_NewException("select.error", NULL, NULL);\r
1767 Py_INCREF(SelectError);\r
1768 PyModule_AddObject(m, "error", SelectError);\r
1769\r
1770#ifdef PIPE_BUF\r
1771#ifdef HAVE_BROKEN_PIPE_BUF\r
1772#undef PIPE_BUF\r
1773#define PIPE_BUF 512\r
1774#endif\r
1775 PyModule_AddIntConstant(m, "PIPE_BUF", PIPE_BUF);\r
1776#endif\r
1777\r
1778#if defined(HAVE_POLL)\r
1779#ifdef __APPLE__\r
1780 if (select_have_broken_poll()) {\r
1781 if (PyObject_DelAttrString(m, "poll") == -1) {\r
1782 PyErr_Clear();\r
1783 }\r
1784 } else {\r
1785#else\r
1786 {\r
1787#endif\r
1788 Py_TYPE(&poll_Type) = &PyType_Type;\r
1789 PyModule_AddIntConstant(m, "POLLIN", POLLIN);\r
1790 PyModule_AddIntConstant(m, "POLLPRI", POLLPRI);\r
1791 PyModule_AddIntConstant(m, "POLLOUT", POLLOUT);\r
1792 PyModule_AddIntConstant(m, "POLLERR", POLLERR);\r
1793 PyModule_AddIntConstant(m, "POLLHUP", POLLHUP);\r
1794 PyModule_AddIntConstant(m, "POLLNVAL", POLLNVAL);\r
1795\r
1796#ifdef POLLRDNORM\r
1797 PyModule_AddIntConstant(m, "POLLRDNORM", POLLRDNORM);\r
1798#endif\r
1799#ifdef POLLRDBAND\r
1800 PyModule_AddIntConstant(m, "POLLRDBAND", POLLRDBAND);\r
1801#endif\r
1802#ifdef POLLWRNORM\r
1803 PyModule_AddIntConstant(m, "POLLWRNORM", POLLWRNORM);\r
1804#endif\r
1805#ifdef POLLWRBAND\r
1806 PyModule_AddIntConstant(m, "POLLWRBAND", POLLWRBAND);\r
1807#endif\r
1808#ifdef POLLMSG\r
1809 PyModule_AddIntConstant(m, "POLLMSG", POLLMSG);\r
1810#endif\r
1811 }\r
1812#endif /* HAVE_POLL */\r
1813\r
1814#ifdef HAVE_EPOLL\r
1815 Py_TYPE(&pyEpoll_Type) = &PyType_Type;\r
1816 if (PyType_Ready(&pyEpoll_Type) < 0)\r
1817 return;\r
1818\r
1819 Py_INCREF(&pyEpoll_Type);\r
1820 PyModule_AddObject(m, "epoll", (PyObject *) &pyEpoll_Type);\r
1821\r
1822 PyModule_AddIntConstant(m, "EPOLLIN", EPOLLIN);\r
1823 PyModule_AddIntConstant(m, "EPOLLOUT", EPOLLOUT);\r
1824 PyModule_AddIntConstant(m, "EPOLLPRI", EPOLLPRI);\r
1825 PyModule_AddIntConstant(m, "EPOLLERR", EPOLLERR);\r
1826 PyModule_AddIntConstant(m, "EPOLLHUP", EPOLLHUP);\r
1827 PyModule_AddIntConstant(m, "EPOLLET", EPOLLET);\r
1828#ifdef EPOLLONESHOT\r
1829 /* Kernel 2.6.2+ */\r
1830 PyModule_AddIntConstant(m, "EPOLLONESHOT", EPOLLONESHOT);\r
1831#endif\r
1832 /* PyModule_AddIntConstant(m, "EPOLL_RDHUP", EPOLLRDHUP); */\r
1833 PyModule_AddIntConstant(m, "EPOLLRDNORM", EPOLLRDNORM);\r
1834 PyModule_AddIntConstant(m, "EPOLLRDBAND", EPOLLRDBAND);\r
1835 PyModule_AddIntConstant(m, "EPOLLWRNORM", EPOLLWRNORM);\r
1836 PyModule_AddIntConstant(m, "EPOLLWRBAND", EPOLLWRBAND);\r
1837 PyModule_AddIntConstant(m, "EPOLLMSG", EPOLLMSG);\r
1838#endif /* HAVE_EPOLL */\r
1839\r
1840#ifdef HAVE_KQUEUE\r
1841 kqueue_event_Type.tp_new = PyType_GenericNew;\r
1842 Py_TYPE(&kqueue_event_Type) = &PyType_Type;\r
1843 if(PyType_Ready(&kqueue_event_Type) < 0)\r
1844 return;\r
1845\r
1846 Py_INCREF(&kqueue_event_Type);\r
1847 PyModule_AddObject(m, "kevent", (PyObject *)&kqueue_event_Type);\r
1848\r
1849 Py_TYPE(&kqueue_queue_Type) = &PyType_Type;\r
1850 if(PyType_Ready(&kqueue_queue_Type) < 0)\r
1851 return;\r
1852 Py_INCREF(&kqueue_queue_Type);\r
1853 PyModule_AddObject(m, "kqueue", (PyObject *)&kqueue_queue_Type);\r
1854\r
1855 /* event filters */\r
1856 PyModule_AddIntConstant(m, "KQ_FILTER_READ", EVFILT_READ);\r
1857 PyModule_AddIntConstant(m, "KQ_FILTER_WRITE", EVFILT_WRITE);\r
1858 PyModule_AddIntConstant(m, "KQ_FILTER_AIO", EVFILT_AIO);\r
1859 PyModule_AddIntConstant(m, "KQ_FILTER_VNODE", EVFILT_VNODE);\r
1860 PyModule_AddIntConstant(m, "KQ_FILTER_PROC", EVFILT_PROC);\r
1861#ifdef EVFILT_NETDEV\r
1862 PyModule_AddIntConstant(m, "KQ_FILTER_NETDEV", EVFILT_NETDEV);\r
1863#endif\r
1864 PyModule_AddIntConstant(m, "KQ_FILTER_SIGNAL", EVFILT_SIGNAL);\r
1865 PyModule_AddIntConstant(m, "KQ_FILTER_TIMER", EVFILT_TIMER);\r
1866\r
1867 /* event flags */\r
1868 PyModule_AddIntConstant(m, "KQ_EV_ADD", EV_ADD);\r
1869 PyModule_AddIntConstant(m, "KQ_EV_DELETE", EV_DELETE);\r
1870 PyModule_AddIntConstant(m, "KQ_EV_ENABLE", EV_ENABLE);\r
1871 PyModule_AddIntConstant(m, "KQ_EV_DISABLE", EV_DISABLE);\r
1872 PyModule_AddIntConstant(m, "KQ_EV_ONESHOT", EV_ONESHOT);\r
1873 PyModule_AddIntConstant(m, "KQ_EV_CLEAR", EV_CLEAR);\r
1874\r
1875 PyModule_AddIntConstant(m, "KQ_EV_SYSFLAGS", EV_SYSFLAGS);\r
1876 PyModule_AddIntConstant(m, "KQ_EV_FLAG1", EV_FLAG1);\r
1877\r
1878 PyModule_AddIntConstant(m, "KQ_EV_EOF", EV_EOF);\r
1879 PyModule_AddIntConstant(m, "KQ_EV_ERROR", EV_ERROR);\r
1880\r
1881 /* READ WRITE filter flag */\r
1882 PyModule_AddIntConstant(m, "KQ_NOTE_LOWAT", NOTE_LOWAT);\r
1883\r
1884 /* VNODE filter flags */\r
1885 PyModule_AddIntConstant(m, "KQ_NOTE_DELETE", NOTE_DELETE);\r
1886 PyModule_AddIntConstant(m, "KQ_NOTE_WRITE", NOTE_WRITE);\r
1887 PyModule_AddIntConstant(m, "KQ_NOTE_EXTEND", NOTE_EXTEND);\r
1888 PyModule_AddIntConstant(m, "KQ_NOTE_ATTRIB", NOTE_ATTRIB);\r
1889 PyModule_AddIntConstant(m, "KQ_NOTE_LINK", NOTE_LINK);\r
1890 PyModule_AddIntConstant(m, "KQ_NOTE_RENAME", NOTE_RENAME);\r
1891 PyModule_AddIntConstant(m, "KQ_NOTE_REVOKE", NOTE_REVOKE);\r
1892\r
1893 /* PROC filter flags */\r
1894 PyModule_AddIntConstant(m, "KQ_NOTE_EXIT", NOTE_EXIT);\r
1895 PyModule_AddIntConstant(m, "KQ_NOTE_FORK", NOTE_FORK);\r
1896 PyModule_AddIntConstant(m, "KQ_NOTE_EXEC", NOTE_EXEC);\r
1897 PyModule_AddIntConstant(m, "KQ_NOTE_PCTRLMASK", NOTE_PCTRLMASK);\r
1898 PyModule_AddIntConstant(m, "KQ_NOTE_PDATAMASK", NOTE_PDATAMASK);\r
1899\r
1900 PyModule_AddIntConstant(m, "KQ_NOTE_TRACK", NOTE_TRACK);\r
1901 PyModule_AddIntConstant(m, "KQ_NOTE_CHILD", NOTE_CHILD);\r
1902 PyModule_AddIntConstant(m, "KQ_NOTE_TRACKERR", NOTE_TRACKERR);\r
1903\r
1904 /* NETDEV filter flags */\r
1905#ifdef EVFILT_NETDEV\r
1906 PyModule_AddIntConstant(m, "KQ_NOTE_LINKUP", NOTE_LINKUP);\r
1907 PyModule_AddIntConstant(m, "KQ_NOTE_LINKDOWN", NOTE_LINKDOWN);\r
1908 PyModule_AddIntConstant(m, "KQ_NOTE_LINKINV", NOTE_LINKINV);\r
1909#endif\r
1910\r
1911#endif /* HAVE_KQUEUE */\r
1912}\r