diff options
Diffstat (limited to 'Modules/selectmodule.c')
-rw-r--r-- | Modules/selectmodule.c | 242 |
1 files changed, 174 insertions, 68 deletions
diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c index c492224ecb..d44e8de929 100644 --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -47,19 +47,11 @@ extern void bzero(void *, int); #include <sys/types.h> #endif -#if defined(PYOS_OS2) && !defined(PYCC_GCC) -#include <sys/time.h> -#include <utils.h> -#endif - #ifdef MS_WINDOWS # define WIN32_LEAN_AND_MEAN # include <winsock.h> #else # define SOCKET int -# if defined(__VMS) -# include <socket.h> -# endif #endif /* list of Python objects and their file descriptor */ @@ -304,9 +296,9 @@ select_select(PyObject *self, PyObject *args) else ret = PyTuple_Pack(3, ifdlist, ofdlist, efdlist); - Py_DECREF(ifdlist); - Py_DECREF(ofdlist); - Py_DECREF(efdlist); + Py_XDECREF(ifdlist); + Py_XDECREF(ofdlist); + Py_XDECREF(efdlist); } finally: @@ -706,6 +698,13 @@ typedef struct { static PyTypeObject devpoll_Type; +static PyObject * +devpoll_err_closed(void) +{ + PyErr_SetString(PyExc_ValueError, "I/O operation on closed devpoll object"); + return NULL; +} + static int devpoll_flush(devpollObject *self) { int size, n; @@ -747,6 +746,9 @@ internal_devpoll_register(devpollObject *self, PyObject *args, int remove) int fd; unsigned short events = POLLIN | POLLPRI | POLLOUT; + if (self->fd_devpoll < 0) + return devpoll_err_closed(); + if (!PyArg_ParseTuple(args, "O|O&:register", &o, ushort_converter, &events)) return NULL; @@ -810,6 +812,9 @@ devpoll_unregister(devpollObject *self, PyObject *o) { int fd; + if (self->fd_devpoll < 0) + return devpoll_err_closed(); + fd = PyObject_AsFileDescriptor( o ); if (fd == -1) return NULL; @@ -839,6 +844,9 @@ devpoll_poll(devpollObject *self, PyObject *args) long timeout; PyObject *value, *num1, *num2; + if (self->fd_devpoll < 0) + return devpoll_err_closed(); + if (!PyArg_UnpackTuple(args, "poll", 0, 1, &tout)) { return NULL; } @@ -917,6 +925,60 @@ devpoll_poll(devpollObject *self, PyObject *args) return NULL; } +static int +devpoll_internal_close(devpollObject *self) +{ + int save_errno = 0; + if (self->fd_devpoll >= 0) { + int fd = self->fd_devpoll; + self->fd_devpoll = -1; + Py_BEGIN_ALLOW_THREADS + if (close(fd) < 0) + save_errno = errno; + Py_END_ALLOW_THREADS + } + return save_errno; +} + +static PyObject* +devpoll_close(devpollObject *self) +{ + errno = devpoll_internal_close(self); + if (errno < 0) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + Py_RETURN_NONE; +} + +PyDoc_STRVAR(devpoll_close_doc, +"close() -> None\n\ +\n\ +Close the devpoll file descriptor. Further operations on the devpoll\n\ +object will raise an exception."); + +static PyObject* +devpoll_get_closed(devpollObject *self) +{ + if (self->fd_devpoll < 0) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; +} + +static PyObject* +devpoll_fileno(devpollObject *self) +{ + if (self->fd_devpoll < 0) + return devpoll_err_closed(); + return PyLong_FromLong(self->fd_devpoll); +} + +PyDoc_STRVAR(devpoll_fileno_doc, +"fileno() -> int\n\ +\n\ +Return the file descriptor."); + static PyMethodDef devpoll_methods[] = { {"register", (PyCFunction)devpoll_register, METH_VARARGS, devpoll_register_doc}, @@ -926,9 +988,19 @@ static PyMethodDef devpoll_methods[] = { METH_O, devpoll_unregister_doc}, {"poll", (PyCFunction)devpoll_poll, METH_VARARGS, devpoll_poll_doc}, + {"close", (PyCFunction)devpoll_close, METH_NOARGS, + devpoll_close_doc}, + {"fileno", (PyCFunction)devpoll_fileno, METH_NOARGS, + devpoll_fileno_doc}, {NULL, NULL} /* sentinel */ }; +static PyGetSetDef devpoll_getsetlist[] = { + {"closed", (getter)devpoll_get_closed, NULL, + "True if the devpoll object is closed"}, + {0}, +}; + static devpollObject * newDevPollObject(void) { @@ -946,7 +1018,7 @@ newDevPollObject(void) */ limit_result = getrlimit(RLIMIT_NOFILE, &limit); if (limit_result != -1) - fd_devpoll = open("/dev/poll", O_RDWR); + fd_devpoll = _Py_open("/dev/poll", O_RDWR); Py_END_ALLOW_THREADS if (limit_result == -1) { @@ -982,12 +1054,8 @@ newDevPollObject(void) static void devpoll_dealloc(devpollObject *self) { - Py_BEGIN_ALLOW_THREADS - close(self->fd_devpoll); - Py_END_ALLOW_THREADS - + (void)devpoll_internal_close(self); PyMem_DEL(self->fds); - PyObject_Del(self); } @@ -1023,6 +1091,8 @@ static PyTypeObject devpoll_Type = { 0, /*tp_iter*/ 0, /*tp_iternext*/ devpoll_methods, /*tp_methods*/ + 0, /* tp_members */ + devpoll_getsetlist, /* tp_getset */ }; #endif /* HAVE_SYS_DEVPOLL_H */ @@ -1106,7 +1176,7 @@ static PyTypeObject pyEpoll_Type; static PyObject * pyepoll_err_closed(void) { - PyErr_SetString(PyExc_ValueError, "I/O operation on closed epoll fd"); + PyErr_SetString(PyExc_ValueError, "I/O operation on closed epoll object"); return NULL; } @@ -1138,6 +1208,7 @@ newPyEpoll_Object(PyTypeObject *type, int sizehint, int flags, SOCKET fd) if (fd == -1) { Py_BEGIN_ALLOW_THREADS #ifdef HAVE_EPOLL_CREATE1 + flags |= EPOLL_CLOEXEC; if (flags) self->epfd = epoll_create1(flags); else @@ -1153,6 +1224,14 @@ newPyEpoll_Object(PyTypeObject *type, int sizehint, int flags, SOCKET fd) PyErr_SetFromErrno(PyExc_OSError); return NULL; } + +#ifndef HAVE_EPOLL_CREATE1 + if (fd == -1 && _Py_set_inheritable(self->epfd, 0, NULL) < 0) { + Py_DECREF(self); + return NULL; + } +#endif + return (PyObject *)self; } @@ -1252,16 +1331,16 @@ pyepoll_internal_ctl(int epfd, int op, PyObject *pfd, unsigned int events) return NULL; } - switch(op) { - case EPOLL_CTL_ADD: - case EPOLL_CTL_MOD: + switch (op) { + case EPOLL_CTL_ADD: + case EPOLL_CTL_MOD: ev.events = events; ev.data.fd = fd; Py_BEGIN_ALLOW_THREADS result = epoll_ctl(epfd, op, fd, &ev); Py_END_ALLOW_THREADS break; - case EPOLL_CTL_DEL: + case EPOLL_CTL_DEL: /* In kernel versions before 2.6.9, the EPOLL_CTL_DEL * operation required a non-NULL pointer in event, even * though this argument is ignored. */ @@ -1274,7 +1353,7 @@ pyepoll_internal_ctl(int epfd, int op, PyObject *pfd, unsigned int events) } Py_END_ALLOW_THREADS break; - default: + default: result = -1; errno = EINVAL; } @@ -1394,7 +1473,6 @@ pyepoll_poll(pyEpoll_Object *self, PyObject *args, PyObject *kwds) evs = PyMem_New(struct epoll_event, maxevents); if (evs == NULL) { - Py_DECREF(self); PyErr_NoMemory(); return NULL; } @@ -1433,6 +1511,24 @@ Wait for events on the epoll file descriptor for a maximum time of timeout\n\ in seconds (as float). -1 makes poll wait indefinitely.\n\ Up to maxevents are returned to the caller."); +static PyObject * +pyepoll_enter(pyEpoll_Object *self, PyObject *args) +{ + if (self->epfd < 0) + return pyepoll_err_closed(); + + Py_INCREF(self); + return (PyObject *)self; +} + +static PyObject * +pyepoll_exit(PyObject *self, PyObject *args) +{ + _Py_IDENTIFIER(close); + + return _PyObject_CallMethodId(self, &PyId_close, NULL); +} + static PyMethodDef pyepoll_methods[] = { {"fromfd", (PyCFunction)pyepoll_fromfd, METH_VARARGS | METH_CLASS, pyepoll_fromfd_doc}, @@ -1448,6 +1544,10 @@ static PyMethodDef pyepoll_methods[] = { METH_VARARGS | METH_KEYWORDS, pyepoll_unregister_doc}, {"poll", (PyCFunction)pyepoll_poll, METH_VARARGS | METH_KEYWORDS, pyepoll_poll_doc}, + {"__enter__", (PyCFunction)pyepoll_enter, METH_NOARGS, + NULL}, + {"__exit__", (PyCFunction)pyepoll_exit, METH_VARARGS, + NULL}, {NULL, NULL}, }; @@ -1605,17 +1705,17 @@ static PyTypeObject kqueue_queue_Type; * kevent is not standard and its members vary across BSDs. */ #if !defined(__OpenBSD__) -# define IDENT_TYPE T_UINTPTRT -# define IDENT_CAST Py_intptr_t -# define DATA_TYPE T_INTPTRT +# define IDENT_TYPE T_UINTPTRT +# define IDENT_CAST Py_intptr_t +# define DATA_TYPE T_INTPTRT # define DATA_FMT_UNIT INTPTRT_FMT_UNIT -# define IDENT_AsType PyLong_AsUintptr_t +# define IDENT_AsType PyLong_AsUintptr_t #else -# define IDENT_TYPE T_UINT -# define IDENT_CAST int -# define DATA_TYPE T_INT +# define IDENT_TYPE T_UINT +# define IDENT_CAST int +# define DATA_TYPE T_INT # define DATA_FMT_UNIT "i" -# define IDENT_AsType PyLong_AsUnsignedLong +# define IDENT_AsType PyLong_AsUnsignedLong #endif /* Unfortunately, we can't store python objects in udata, because @@ -1667,7 +1767,7 @@ kqueue_event_init(kqueue_event_Object *self, PyObject *args, PyObject *kwds) if (PyLong_Check(pfd) #if IDENT_TYPE == T_UINT - && PyLong_AsUnsignedLong(pfd) <= UINT_MAX + && PyLong_AsUnsignedLong(pfd) <= UINT_MAX #endif ) { self->e.ident = IDENT_AsType(pfd); @@ -1709,22 +1809,22 @@ kqueue_event_richcompare(kqueue_event_Object *s, kqueue_event_Object *o, } switch (op) { - case Py_EQ: + case Py_EQ: result = (result == 0); break; - case Py_NE: + case Py_NE: result = (result != 0); break; - case Py_LE: + case Py_LE: result = (result <= 0); break; - case Py_GE: + case Py_GE: result = (result >= 0); break; - case Py_LT: + case Py_LT: result = (result < 0); break; - case Py_GT: + case Py_GT: result = (result > 0); break; } @@ -1776,7 +1876,7 @@ static PyTypeObject kqueue_event_Type = { static PyObject * kqueue_queue_err_closed(void) { - PyErr_SetString(PyExc_ValueError, "I/O operation on closed kqueue fd"); + PyErr_SetString(PyExc_ValueError, "I/O operation on closed kqueue object"); return NULL; } @@ -1818,13 +1918,19 @@ newKqueue_Object(PyTypeObject *type, SOCKET fd) PyErr_SetFromErrno(PyExc_OSError); return NULL; } + + if (fd == -1) { + if (_Py_set_inheritable(self->kqfd, 0, NULL) < 0) { + Py_DECREF(self); + return NULL; + } + } return (PyObject *)self; } static PyObject * kqueue_queue_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - if ((args != NULL && PyObject_Size(args)) || (kwds != NULL && PyObject_Size(kwds))) { PyErr_SetString(PyExc_ValueError, @@ -2144,7 +2250,7 @@ arguments; each contains the subset of the corresponding file descriptors\n\ that are ready.\n\ \n\ *** IMPORTANT NOTICE ***\n\ -On Windows and OpenVMS, only sockets are supported; on Unix, all file\n\ +On Windows only sockets are supported; on Unix, all file\n\ descriptors can be used."); static PyMethodDef select_methods[] = { @@ -2162,7 +2268,7 @@ PyDoc_STRVAR(module_doc, "This module supports asynchronous I/O on multiple file descriptors.\n\ \n\ *** IMPORTANT NOTICE ***\n\ -On Windows and OpenVMS, only sockets are supported; on Unix, all file descriptors."); +On Windows only sockets are supported; on Unix, all file descriptors."); static struct PyModuleDef selectmodule = { @@ -2196,7 +2302,7 @@ PyInit_select(void) #undef PIPE_BUF #define PIPE_BUF 512 #endif - PyModule_AddIntConstant(m, "PIPE_BUF", PIPE_BUF); + PyModule_AddIntMacro(m, PIPE_BUF); #endif #if defined(HAVE_POLL) && !defined(HAVE_BROKEN_POLL) @@ -2211,27 +2317,27 @@ PyInit_select(void) #endif if (PyType_Ready(&poll_Type) < 0) return NULL; - PyModule_AddIntConstant(m, "POLLIN", POLLIN); - PyModule_AddIntConstant(m, "POLLPRI", POLLPRI); - PyModule_AddIntConstant(m, "POLLOUT", POLLOUT); - PyModule_AddIntConstant(m, "POLLERR", POLLERR); - PyModule_AddIntConstant(m, "POLLHUP", POLLHUP); - PyModule_AddIntConstant(m, "POLLNVAL", POLLNVAL); + PyModule_AddIntMacro(m, POLLIN); + PyModule_AddIntMacro(m, POLLPRI); + PyModule_AddIntMacro(m, POLLOUT); + PyModule_AddIntMacro(m, POLLERR); + PyModule_AddIntMacro(m, POLLHUP); + PyModule_AddIntMacro(m, POLLNVAL); #ifdef POLLRDNORM - PyModule_AddIntConstant(m, "POLLRDNORM", POLLRDNORM); + PyModule_AddIntMacro(m, POLLRDNORM); #endif #ifdef POLLRDBAND - PyModule_AddIntConstant(m, "POLLRDBAND", POLLRDBAND); + PyModule_AddIntMacro(m, POLLRDBAND); #endif #ifdef POLLWRNORM - PyModule_AddIntConstant(m, "POLLWRNORM", POLLWRNORM); + PyModule_AddIntMacro(m, POLLWRNORM); #endif #ifdef POLLWRBAND - PyModule_AddIntConstant(m, "POLLWRBAND", POLLWRBAND); + PyModule_AddIntMacro(m, POLLWRBAND); #endif #ifdef POLLMSG - PyModule_AddIntConstant(m, "POLLMSG", POLLMSG); + PyModule_AddIntMacro(m, POLLMSG); #endif } #endif /* HAVE_POLL */ @@ -2249,25 +2355,25 @@ PyInit_select(void) Py_INCREF(&pyEpoll_Type); PyModule_AddObject(m, "epoll", (PyObject *) &pyEpoll_Type); - PyModule_AddIntConstant(m, "EPOLLIN", EPOLLIN); - PyModule_AddIntConstant(m, "EPOLLOUT", EPOLLOUT); - PyModule_AddIntConstant(m, "EPOLLPRI", EPOLLPRI); - PyModule_AddIntConstant(m, "EPOLLERR", EPOLLERR); - PyModule_AddIntConstant(m, "EPOLLHUP", EPOLLHUP); - PyModule_AddIntConstant(m, "EPOLLET", EPOLLET); + PyModule_AddIntMacro(m, EPOLLIN); + PyModule_AddIntMacro(m, EPOLLOUT); + PyModule_AddIntMacro(m, EPOLLPRI); + PyModule_AddIntMacro(m, EPOLLERR); + PyModule_AddIntMacro(m, EPOLLHUP); + PyModule_AddIntMacro(m, EPOLLET); #ifdef EPOLLONESHOT /* Kernel 2.6.2+ */ - PyModule_AddIntConstant(m, "EPOLLONESHOT", EPOLLONESHOT); + PyModule_AddIntMacro(m, EPOLLONESHOT); #endif /* PyModule_AddIntConstant(m, "EPOLL_RDHUP", EPOLLRDHUP); */ - PyModule_AddIntConstant(m, "EPOLLRDNORM", EPOLLRDNORM); - PyModule_AddIntConstant(m, "EPOLLRDBAND", EPOLLRDBAND); - PyModule_AddIntConstant(m, "EPOLLWRNORM", EPOLLWRNORM); - PyModule_AddIntConstant(m, "EPOLLWRBAND", EPOLLWRBAND); - PyModule_AddIntConstant(m, "EPOLLMSG", EPOLLMSG); + PyModule_AddIntMacro(m, EPOLLRDNORM); + PyModule_AddIntMacro(m, EPOLLRDBAND); + PyModule_AddIntMacro(m, EPOLLWRNORM); + PyModule_AddIntMacro(m, EPOLLWRBAND); + PyModule_AddIntMacro(m, EPOLLMSG); #ifdef EPOLL_CLOEXEC - PyModule_AddIntConstant(m, "EPOLL_CLOEXEC", EPOLL_CLOEXEC); + PyModule_AddIntMacro(m, EPOLL_CLOEXEC); #endif #endif /* HAVE_EPOLL */ |