Back to index

python3.2  3.2.2
Classes | Defines | Functions | Variables
selectmodule.c File Reference
#include "Python.h"
#include <structmember.h>

Go to the source code of this file.

Classes

struct  pylist

Defines

#define SOCKET   int

Functions

static void reap_obj (pylist fd2obj[FD_SETSIZE+1])
static int seq2set (PyObject *seq, fd_set *set, pylist fd2obj[FD_SETSIZE+1])
static PyObjectset2list (fd_set *set, pylist fd2obj[FD_SETSIZE+1])
static PyObjectselect_select (PyObject *self, PyObject *args)
 PyDoc_STRVAR (select_doc,"select(rlist, wlist, xlist[, timeout]) -> (rlist, wlist, xlist)\n\ \n\ Wait until one or more file descriptors are ready for some kind of I/O.\n\ The first three arguments are sequences of file descriptors to be waited for:\n\ rlist -- wait until ready for reading\n\ wlist -- wait until ready for writing\n\ xlist -- wait for an ``exceptional condition''\n\ If only one kind of condition is required, pass [] for the other lists.\n\ A file descriptor is either a socket or file object, or a small integer\n\ gotten from a fileno() method call on one of those.\n\ \n\ The optional 4th argument specifies a timeout in seconds; it may be\n\ a floating point number to specify fractions of seconds. If it is absent\n\ or None, the call will never time out.\n\ \n\ The return value is a tuple of three lists corresponding to the first three\n\ 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\ descriptors can be used.")
 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.")
PyMODINIT_FUNC PyInit_select (void)

Variables

static PyObjectSelectError
static PyMethodDef select_methods []
static struct PyModuleDef

Class Documentation

struct pylist

Definition at line 60 of file selectmodule.c.

Collaboration diagram for pylist:
Class Members
SOCKET fd
PyObject * obj
int sentinel

Define Documentation

#define SOCKET   int

Definition at line 51 of file selectmodule.c.


Function Documentation

PyDoc_STRVAR ( select_doc  ,
"select(rlist, wlist, xlist[, timeout]) -> (rlist, wlist, xlist)\n\\n\Wait until one or more file descriptors are ready for some kind of I/O.\n\The first three arguments are sequences of file descriptors to be waited for:\n\rlist -- wait until ready for reading\n\wlist -- wait until ready for writing\n\xlist -- wait for an ``exceptional condition''\n\If only one kind of condition is  required,
pass[]for the other lists.\n\A file descriptor is either a socket or file  object,
or a small integer\n\gotten from a fileno() method call on one of those.\n\\n\The optional 4th argument specifies a timeout in seconds;it may be\n\a floating point number to specify fractions of seconds.If it is absent\n\or  None,
the call will never time out.\n\\n\The return value is a tuple of three lists corresponding to the first three\n\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\descriptors can be used."   
)
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."   
)

Definition at line 1776 of file selectmodule.c.

{
    PyObject *m;
    m = PyModule_Create(&selectmodule);
    if (m == NULL)
        return NULL;

    SelectError = PyErr_NewException("select.error", NULL, NULL);
    Py_INCREF(SelectError);
    PyModule_AddObject(m, "error", SelectError);

#ifdef PIPE_BUF
#ifdef HAVE_BROKEN_PIPE_BUF
#undef PIPE_BUF
#define PIPE_BUF 512
#endif
    PyModule_AddIntConstant(m, "PIPE_BUF", PIPE_BUF);
#endif

#if defined(HAVE_POLL)
#ifdef __APPLE__
    if (select_have_broken_poll()) {
        if (PyObject_DelAttrString(m, "poll") == -1) {
            PyErr_Clear();
        }
    } else {
#else
    {
#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);

#ifdef POLLRDNORM
        PyModule_AddIntConstant(m, "POLLRDNORM", POLLRDNORM);
#endif
#ifdef POLLRDBAND
        PyModule_AddIntConstant(m, "POLLRDBAND", POLLRDBAND);
#endif
#ifdef POLLWRNORM
        PyModule_AddIntConstant(m, "POLLWRNORM", POLLWRNORM);
#endif
#ifdef POLLWRBAND
        PyModule_AddIntConstant(m, "POLLWRBAND", POLLWRBAND);
#endif
#ifdef POLLMSG
        PyModule_AddIntConstant(m, "POLLMSG", POLLMSG);
#endif
    }
#endif /* HAVE_POLL */

#ifdef HAVE_EPOLL
    Py_TYPE(&pyEpoll_Type) = &PyType_Type;
    if (PyType_Ready(&pyEpoll_Type) < 0)
        return NULL;

    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);
#ifdef EPOLLONESHOT
    /* Kernel 2.6.2+ */
    PyModule_AddIntConstant(m, "EPOLLONESHOT", 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);
#endif /* HAVE_EPOLL */

#ifdef HAVE_KQUEUE
    kqueue_event_Type.tp_new = PyType_GenericNew;
    Py_TYPE(&kqueue_event_Type) = &PyType_Type;
    if(PyType_Ready(&kqueue_event_Type) < 0)
        return NULL;

    Py_INCREF(&kqueue_event_Type);
    PyModule_AddObject(m, "kevent", (PyObject *)&kqueue_event_Type);

    Py_TYPE(&kqueue_queue_Type) = &PyType_Type;
    if(PyType_Ready(&kqueue_queue_Type) < 0)
        return NULL;
    Py_INCREF(&kqueue_queue_Type);
    PyModule_AddObject(m, "kqueue", (PyObject *)&kqueue_queue_Type);

    /* event filters */
    PyModule_AddIntConstant(m, "KQ_FILTER_READ", EVFILT_READ);
    PyModule_AddIntConstant(m, "KQ_FILTER_WRITE", EVFILT_WRITE);
    PyModule_AddIntConstant(m, "KQ_FILTER_AIO", EVFILT_AIO);
    PyModule_AddIntConstant(m, "KQ_FILTER_VNODE", EVFILT_VNODE);
    PyModule_AddIntConstant(m, "KQ_FILTER_PROC", EVFILT_PROC);
#ifdef EVFILT_NETDEV
    PyModule_AddIntConstant(m, "KQ_FILTER_NETDEV", EVFILT_NETDEV);
#endif
    PyModule_AddIntConstant(m, "KQ_FILTER_SIGNAL", EVFILT_SIGNAL);
    PyModule_AddIntConstant(m, "KQ_FILTER_TIMER", EVFILT_TIMER);

    /* event flags */
    PyModule_AddIntConstant(m, "KQ_EV_ADD", EV_ADD);
    PyModule_AddIntConstant(m, "KQ_EV_DELETE", EV_DELETE);
    PyModule_AddIntConstant(m, "KQ_EV_ENABLE", EV_ENABLE);
    PyModule_AddIntConstant(m, "KQ_EV_DISABLE", EV_DISABLE);
    PyModule_AddIntConstant(m, "KQ_EV_ONESHOT", EV_ONESHOT);
    PyModule_AddIntConstant(m, "KQ_EV_CLEAR", EV_CLEAR);

    PyModule_AddIntConstant(m, "KQ_EV_SYSFLAGS", EV_SYSFLAGS);
    PyModule_AddIntConstant(m, "KQ_EV_FLAG1", EV_FLAG1);

    PyModule_AddIntConstant(m, "KQ_EV_EOF", EV_EOF);
    PyModule_AddIntConstant(m, "KQ_EV_ERROR", EV_ERROR);

    /* READ WRITE filter flag */
    PyModule_AddIntConstant(m, "KQ_NOTE_LOWAT", NOTE_LOWAT);

    /* VNODE filter flags  */
    PyModule_AddIntConstant(m, "KQ_NOTE_DELETE", NOTE_DELETE);
    PyModule_AddIntConstant(m, "KQ_NOTE_WRITE", NOTE_WRITE);
    PyModule_AddIntConstant(m, "KQ_NOTE_EXTEND", NOTE_EXTEND);
    PyModule_AddIntConstant(m, "KQ_NOTE_ATTRIB", NOTE_ATTRIB);
    PyModule_AddIntConstant(m, "KQ_NOTE_LINK", NOTE_LINK);
    PyModule_AddIntConstant(m, "KQ_NOTE_RENAME", NOTE_RENAME);
    PyModule_AddIntConstant(m, "KQ_NOTE_REVOKE", NOTE_REVOKE);

    /* PROC filter flags  */
    PyModule_AddIntConstant(m, "KQ_NOTE_EXIT", NOTE_EXIT);
    PyModule_AddIntConstant(m, "KQ_NOTE_FORK", NOTE_FORK);
    PyModule_AddIntConstant(m, "KQ_NOTE_EXEC", NOTE_EXEC);
    PyModule_AddIntConstant(m, "KQ_NOTE_PCTRLMASK", NOTE_PCTRLMASK);
    PyModule_AddIntConstant(m, "KQ_NOTE_PDATAMASK", NOTE_PDATAMASK);

    PyModule_AddIntConstant(m, "KQ_NOTE_TRACK", NOTE_TRACK);
    PyModule_AddIntConstant(m, "KQ_NOTE_CHILD", NOTE_CHILD);
    PyModule_AddIntConstant(m, "KQ_NOTE_TRACKERR", NOTE_TRACKERR);

    /* NETDEV filter flags */
#ifdef EVFILT_NETDEV
    PyModule_AddIntConstant(m, "KQ_NOTE_LINKUP", NOTE_LINKUP);
    PyModule_AddIntConstant(m, "KQ_NOTE_LINKDOWN", NOTE_LINKDOWN);
    PyModule_AddIntConstant(m, "KQ_NOTE_LINKINV", NOTE_LINKINV);
#endif

#endif /* HAVE_KQUEUE */
    return m;
}

Here is the call graph for this function:

static void reap_obj ( pylist  fd2obj[FD_SETSIZE+1]) [static]

Definition at line 67 of file selectmodule.c.

{
    int i;
    for (i = 0; i < FD_SETSIZE + 1 && fd2obj[i].sentinel >= 0; i++) {
        Py_XDECREF(fd2obj[i].obj);
        fd2obj[i].obj = NULL;
    }
    fd2obj[0].sentinel = -1;
}

Here is the caller graph for this function:

static PyObject* select_select ( PyObject self,
PyObject args 
) [static]

Definition at line 191 of file selectmodule.c.

{
#ifdef SELECT_USES_HEAP
    pylist *rfd2obj, *wfd2obj, *efd2obj;
#else  /* !SELECT_USES_HEAP */
    /* XXX: All this should probably be implemented as follows:
     * - find the highest descriptor we're interested in
     * - add one
     * - that's the size
     * See: Stevens, APitUE, $12.5.1
     */
    pylist rfd2obj[FD_SETSIZE + 1];
    pylist wfd2obj[FD_SETSIZE + 1];
    pylist efd2obj[FD_SETSIZE + 1];
#endif /* SELECT_USES_HEAP */
    PyObject *ifdlist, *ofdlist, *efdlist;
    PyObject *ret = NULL;
    PyObject *tout = Py_None;
    fd_set ifdset, ofdset, efdset;
    double timeout;
    struct timeval tv, *tvp;
    long seconds;
    int imax, omax, emax, max;
    int n;

    /* convert arguments */
    if (!PyArg_UnpackTuple(args, "select", 3, 4,
                          &ifdlist, &ofdlist, &efdlist, &tout))
        return NULL;

    if (tout == Py_None)
        tvp = (struct timeval *)0;
    else if (!PyNumber_Check(tout)) {
        PyErr_SetString(PyExc_TypeError,
                        "timeout must be a float or None");
        return NULL;
    }
    else {
        timeout = PyFloat_AsDouble(tout);
        if (timeout == -1 && PyErr_Occurred())
            return NULL;
        if (timeout > (double)LONG_MAX) {
            PyErr_SetString(PyExc_OverflowError,
                            "timeout period too long");
            return NULL;
        }
        seconds = (long)timeout;
        timeout = timeout - (double)seconds;
        tv.tv_sec = seconds;
        tv.tv_usec = (long)(timeout * 1E6);
        tvp = &tv;
    }


#ifdef SELECT_USES_HEAP
    /* Allocate memory for the lists */
    rfd2obj = PyMem_NEW(pylist, FD_SETSIZE + 1);
    wfd2obj = PyMem_NEW(pylist, FD_SETSIZE + 1);
    efd2obj = PyMem_NEW(pylist, FD_SETSIZE + 1);
    if (rfd2obj == NULL || wfd2obj == NULL || efd2obj == NULL) {
        if (rfd2obj) PyMem_DEL(rfd2obj);
        if (wfd2obj) PyMem_DEL(wfd2obj);
        if (efd2obj) PyMem_DEL(efd2obj);
        return PyErr_NoMemory();
    }
#endif /* SELECT_USES_HEAP */
    /* Convert sequences to fd_sets, and get maximum fd number
     * propagates the Python exception set in seq2set()
     */
    rfd2obj[0].sentinel = -1;
    wfd2obj[0].sentinel = -1;
    efd2obj[0].sentinel = -1;
    if ((imax=seq2set(ifdlist, &ifdset, rfd2obj)) < 0)
        goto finally;
    if ((omax=seq2set(ofdlist, &ofdset, wfd2obj)) < 0)
        goto finally;
    if ((emax=seq2set(efdlist, &efdset, efd2obj)) < 0)
        goto finally;
    max = imax;
    if (omax > max) max = omax;
    if (emax > max) max = emax;

    Py_BEGIN_ALLOW_THREADS
    n = select(max, &ifdset, &ofdset, &efdset, tvp);
    Py_END_ALLOW_THREADS

#ifdef MS_WINDOWS
    if (n == SOCKET_ERROR) {
        PyErr_SetExcFromWindowsErr(SelectError, WSAGetLastError());
    }
#else
    if (n < 0) {
        PyErr_SetFromErrno(SelectError);
    }
#endif
    else {
        /* any of these three calls can raise an exception.  it's more
           convenient to test for this after all three calls... but
           is that acceptable?
        */
        ifdlist = set2list(&ifdset, rfd2obj);
        ofdlist = set2list(&ofdset, wfd2obj);
        efdlist = set2list(&efdset, efd2obj);
        if (PyErr_Occurred())
            ret = NULL;
        else
            ret = PyTuple_Pack(3, ifdlist, ofdlist, efdlist);

        Py_DECREF(ifdlist);
        Py_DECREF(ofdlist);
        Py_DECREF(efdlist);
    }

  finally:
    reap_obj(rfd2obj);
    reap_obj(wfd2obj);
    reap_obj(efd2obj);
#ifdef SELECT_USES_HEAP
    PyMem_DEL(rfd2obj);
    PyMem_DEL(wfd2obj);
    PyMem_DEL(efd2obj);
#endif /* SELECT_USES_HEAP */
    return ret;
}

Here is the call graph for this function:

static int seq2set ( PyObject seq,
fd_set *  set,
pylist  fd2obj[FD_SETSIZE+1] 
) [static]

Definition at line 82 of file selectmodule.c.

{
    int max = -1;
    int index = 0;
    Py_ssize_t i, len = -1;
    PyObject* fast_seq = NULL;
    PyObject* o = NULL;

    fd2obj[0].obj = (PyObject*)0;            /* set list to zero size */
    FD_ZERO(set);

    fast_seq = PySequence_Fast(seq, "arguments 1-3 must be sequences");
    if (!fast_seq)
        return -1;

    len = PySequence_Fast_GET_SIZE(fast_seq);

    for (i = 0; i < len; i++)  {
        SOCKET v;

        /* any intervening fileno() calls could decr this refcnt */
        if (!(o = PySequence_Fast_GET_ITEM(fast_seq, i)))
            return -1;

        Py_INCREF(o);
        v = PyObject_AsFileDescriptor( o );
        if (v == -1) goto finally;

#if defined(_MSC_VER)
        max = 0;                             /* not used for Win32 */
#else  /* !_MSC_VER */
        if (v < 0 || v >= FD_SETSIZE) {
            PyErr_SetString(PyExc_ValueError,
                        "filedescriptor out of range in select()");
            goto finally;
        }
        if (v > max)
            max = v;
#endif /* _MSC_VER */
        FD_SET(v, set);

        /* add object and its file descriptor to the list */
        if (index >= FD_SETSIZE) {
            PyErr_SetString(PyExc_ValueError,
                          "too many file descriptors in select()");
            goto finally;
        }
        fd2obj[index].obj = o;
        fd2obj[index].fd = v;
        fd2obj[index].sentinel = 0;
        fd2obj[++index].sentinel = -1;
    }
    Py_DECREF(fast_seq);
    return max+1;

  finally:
    Py_XDECREF(o);
    Py_DECREF(fast_seq);
    return -1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PyObject* set2list ( fd_set *  set,
pylist  fd2obj[FD_SETSIZE+1] 
) [static]

Definition at line 145 of file selectmodule.c.

{
    int i, j, count=0;
    PyObject *list, *o;
    SOCKET fd;

    for (j = 0; fd2obj[j].sentinel >= 0; j++) {
        if (FD_ISSET(fd2obj[j].fd, set))
            count++;
    }
    list = PyList_New(count);
    if (!list)
        return NULL;

    i = 0;
    for (j = 0; fd2obj[j].sentinel >= 0; j++) {
        fd = fd2obj[j].fd;
        if (FD_ISSET(fd, set)) {
#ifndef _MSC_VER
            if (fd > FD_SETSIZE) {
                PyErr_SetString(PyExc_SystemError,
               "filedescriptor out of range returned in select()");
                goto finally;
            }
#endif
            o = fd2obj[j].obj;
            fd2obj[j].obj = NULL;
            /* transfer ownership */
            if (PyList_SetItem(list, i, o) < 0)
                goto finally;

            i++;
        }
    }
    return list;
  finally:
    Py_DECREF(list);
    return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

struct PyModuleDef [static]
Initial value:
 {
    PyModuleDef_HEAD_INIT,
    "select",
    module_doc,
    -1,
    select_methods,
    NULL,
    NULL,
    NULL,
    NULL
}

Definition at line 1763 of file selectmodule.c.

Initial value:
 {
    {"select",          select_select,  METH_VARARGS,   select_doc},


 
    {0,         0},     
}

Definition at line 1748 of file selectmodule.c.

PyObject* SelectError [static]

Definition at line 57 of file selectmodule.c.