Ticket #1918: issue_1918.patch

File issue_1918.patch, 6.6 KB (added by psykidellic, 7 years ago)

kqueue using the Python select module.

  • twisted/internet/kqreactor.py

     
    1010    | from twisted.internet import kqreactor
    1111    | kqreactor.install()
    1212
    13 This reactor only works on FreeBSD and requires PyKQueue 1.3, which is
    14 available at:  U{http://people.freebsd.org/~dwhite/PyKQueue/}
     13This reactor only works on FreeBSD and requires Python 2.6 and above select.kqueue
     14module or the backport of it for Python 2.5 U{http://pypi.python.org/pypi/select26/0.1a3}
    1515
     16You're going to need to patch select26::
    1617
     18# HG changeset patch -- Bitbucket.org
     19# Project select26
     20# URL http://bitbucket.org/psykidellic/select26/overview/
     21# User psykidellic
     22# Date 1268883306 25200
     23# Node ID aefd0e6a228b32cb4673e32806fcb415ff79152f
     24# Parent  d79af7cb2ea63803bcd621a11aaa3739f882d135
     25Apply the patch
    1726
    18 You're going to need to patch PyKqueue::
     27--- a/select26module.c
     28+++ b/select26module.c
     29@@ -861,7 +861,7 @@ kqueue_queue_control(kqueue_queue_Object
     30        if (nevents < 0) {
     31                PyErr_Format(PyExc_ValueError,
     32                        "Length of eventlist must be 0 or positive, got %d",
     33-                       nchanges);
     34+                       nevents);
     35                return NULL;
     36        }
     37 
     38@@ -927,7 +927,7 @@ kqueue_queue_control(kqueue_queue_Object
     39                                        "select26.kevent objects");
     40                                goto error;
     41                        } else {
     42-                               chl[i] = ((kqueue_event_Object *)ei)->e;
     43+                               chl[i++] = ((kqueue_event_Object *)ei)->e;
     44                        }
     45                        Py_DECREF(ei);
     46                }
    1947
    20     =====================================================
    21     --- PyKQueue-1.3/kqsyscallmodule.c  Sun Jan 28 21:59:50 2001
    22     +++ PyKQueue-1.3/kqsyscallmodule.c.new      Tue Jul 30 18:06:08 2002
    23     @@ -137,7 +137,7 @@
    24      }
    25      
    26      statichere PyTypeObject KQEvent_Type = {
    27     -  PyObject_HEAD_INIT(NULL)
    28     +  PyObject_HEAD_INIT(&PyType_Type)
    29        0,                             // ob_size
    30        "KQEvent",                     // tp_name
    31        sizeof(KQEventObject),         // tp_basicsize
    32     @@ -291,13 +291,14 @@
    33      
    34        /* Build timespec for timeout */
    35        totimespec.tv_sec = timeout / 1000;
    36     -  totimespec.tv_nsec = (timeout % 1000) * 100000;
    37     +  totimespec.tv_nsec = (timeout % 1000) * 1000000;
    38      
    39        // printf("timespec: sec=%d nsec=%d\\n", totimespec.tv_sec, totimespec.tv_nsec);
    40      
    41        /* Make the call */
    42     -
    43     +  Py_BEGIN_ALLOW_THREADS
    44        gotNumEvents = kevent (self->fd, changelist, haveNumEvents, triggered, wantNumEvents, &totimespec);
    45     +  Py_END_ALLOW_THREADS
    46      
    47        /* Don't need the input event list anymore, so get rid of it */
    48        free (changelist);
    49     @@ -361,7 +362,7 @@
    50      statichere PyTypeObject KQueue_Type = {
    51             /* The ob_type field must be initialized in the module init function
    52              * to be portable to Windows without using C++. */
    53     -   PyObject_HEAD_INIT(NULL)
    54     +   PyObject_HEAD_INIT(&PyType_Type)
    55             0,                  /*ob_size*/
    56             "KQueue",                   /*tp_name*/
    57             sizeof(KQueueObject),       /*tp_basicsize*/
     48A complete repo with the change is available at:
     49U{http://bitbucket.org/psykidellic/select26/}
    5850
    5951"""
    6052
     
    6254
    6355from zope.interface import implements
    6456
    65 from kqsyscall import EVFILT_READ, EVFILT_WRITE, EV_DELETE, EV_ADD
    66 from kqsyscall import kqueue, kevent
    67 
     57try:
     58    import select26 as select
     59except ImportError:
     60    import select
     61   
    6862from twisted.internet.interfaces import IReactorFDSet
    6963
    7064from twisted.python import log, failure
     
    10296        Initialize kqueue object, file descriptor tracking dictionaries, and the
    10397        base class.
    10498        """
    105         self._kq = kqueue()
     99        self._kq = select.kqueue()
    106100        self._reads = {}
    107101        self._writes = {}
    108102        self._selectables = {}
     
    110104
    111105
    112106    def _updateRegistration(self, *args):
    113         self._kq.kevent([kevent(*args)], 0, 0)
     107        self._kq.control([select.kevent(*args)], 0, 0)
    114108
    115109    def addReader(self, reader):
    116110        """Add a FileDescriptor for notification of data available to read.
     
    119113        if fd not in self._reads:
    120114            self._selectables[fd] = reader
    121115            self._reads[fd] = 1
    122             self._updateRegistration(fd, EVFILT_READ, EV_ADD)
     116            self._updateRegistration(fd, select.KQ_FILTER_READ, select.KQ_EV_ADD)
    123117
    124118    def addWriter(self, writer):
    125119        """Add a FileDescriptor for notification of data available to write.
     
    128122        if fd not in self._writes:
    129123            self._selectables[fd] = writer
    130124            self._writes[fd] = 1
    131             self._updateRegistration(fd, EVFILT_WRITE, EV_ADD)
     125            self._updateRegistration(fd, select.KQ_FILTER_WRITE, select.KQ_EV_ADD)
    132126
    133127    def removeReader(self, reader):
    134128        """Remove a Selectable for notification of data available to read.
     
    138132            del self._reads[fd]
    139133            if fd not in self._writes:
    140134                del self._selectables[fd]
    141             self._updateRegistration(fd, EVFILT_READ, EV_DELETE)
     135            self._updateRegistration(fd, select.KQ_FILTER_READ, select.KQ_EV_DELETE)
    142136
    143137    def removeWriter(self, writer):
    144138        """Remove a Selectable for notification of data available to write.
     
    148142            del self._writes[fd]
    149143            if fd not in self._reads:
    150144                del self._selectables[fd]
    151             self._updateRegistration(fd, EVFILT_WRITE, EV_DELETE)
     145            self._updateRegistration(fd, select.KQ_FILTER_WRITE, select.KQ_EV_DELETE)
    152146
    153147    def removeAll(self):
    154148        """
     
    169163
    170164    def doKEvent(self, timeout):
    171165        """Poll the kqueue for new events."""
    172         if timeout is None:
    173             timeout = 1000
    174         else:
    175             timeout = int(timeout * 1000) # convert seconds to milliseconds
     166        #if timeout is None:
     167        #    timeout = 1000
     168        #else:
     169        #    timeout = int(timeout * 1000) # convert seconds to milliseconds
    176170
    177171        try:
    178             l = self._kq.kevent([], len(self._selectables), timeout)
     172            l = self._kq.control([], len(self._selectables), timeout)
    179173        except OSError, e:
    180174            if e[0] == errno.EINTR:
    181175                return
     
    195189
    196190    def _doWriteOrRead(self, selectable, fd, filter):
    197191        try:
    198             if filter == EVFILT_READ:
     192            if filter == select.KQ_FILTER_READ:
    199193                why = selectable.doRead()
    200             if filter == EVFILT_WRITE:
     194            if filter == select.KQ_FILTER_WRITE:
    201195                why = selectable.doWrite()
    202196            if not selectable.fileno() == fd:
    203197                why = main.CONNECTION_LOST