Exemple #1
0
    def _unwatchFD(self, fd, descr, flag):
        """
        Unregister a file descriptor with the C{CFRunLoop}, or modify its state
        so that it's listening for only one notification (read or write) as
        opposed to both; used to implement C{removeReader} and C{removeWriter}.

        @param fd: a file descriptor

        @type fd: C{int}

        @param descr: an L{IReadDescriptor} or L{IWriteDescriptor}

        @param flag: C{kCFSocketWriteCallBack} C{kCFSocketReadCallBack}
        """
        if id(descr) not in self._idmap:
            return
        if fd == -1:
            # need to deal with it in this case, I think.
            realfd = self._idmap[id(descr)]
        else:
            realfd = fd
        src, cfs, descr, rw = self._fdmap[realfd]
        CFSocketDisableCallBacks(cfs, flag)
        rw[self._flag2idx(flag)] = False
        if not rw[_READ] and not rw[_WRITE]:
            del self._idmap[id(descr)]
            del self._fdmap[realfd]
            CFRunLoopRemoveSource(self._cfrunloop, src, kCFRunLoopCommonModes)
            CFSocketInvalidate(cfs)
Exemple #2
0
    def _socketCallback(
        self, cfSocket, callbackType, ignoredAddress, ignoredData, context
    ):
        """
        The socket callback issued by CFRunLoop.  This will issue C{doRead} or
        C{doWrite} calls to the L{IReadDescriptor} and L{IWriteDescriptor}
        registered with the file descriptor that we are being notified of.

        @param cfSocket: The C{CFSocket} which has got some activity.

        @param callbackType: The type of activity that we are being notified
            of.  Either C{kCFSocketReadCallBack} or C{kCFSocketWriteCallBack}.

        @param ignoredAddress: Unused, because this is not used for either of
            the callback types we register for.

        @param ignoredData: Unused, because this is not used for either of the
            callback types we register for.

        @param context: The data associated with this callback by
            C{CFSocketCreateWithNative} (in C{CFReactor._watchFD}).  A 2-tuple
            of C{(int, CFRunLoopSource)}.
        """
        (fd, smugglesrc) = context
        if fd not in self._fdmap:
            # Spurious notifications seem to be generated sometimes if you
            # CFSocketDisableCallBacks in the middle of an event.  I don't know
            # about this FD, any more, so let's get rid of it.
            CFRunLoopRemoveSource(self._cfrunloop, smugglesrc, kCFRunLoopCommonModes)
            return

        src, skt, readWriteDescriptor, rw = self._fdmap[fd]

        def _drdw():
            why = None
            isRead = False

            try:
                if readWriteDescriptor.fileno() == -1:
                    why = _NO_FILEDESC
                else:
                    isRead = callbackType == kCFSocketReadCallBack
                    # CFSocket seems to deliver duplicate read/write
                    # notifications sometimes, especially a duplicate
                    # writability notification when first registering the
                    # socket.  This bears further investigation, since I may
                    # have been mis-interpreting the behavior I was seeing.
                    # (Running the full Twisted test suite, while thorough, is
                    # not always entirely clear.) Until this has been more
                    # thoroughly investigated , we consult our own
                    # reading/writing state flags to determine whether we
                    # should actually attempt a doRead/doWrite first.  -glyph
                    if isRead:
                        if rw[_READ]:
                            why = readWriteDescriptor.doRead()
                    else:
                        if rw[_WRITE]:
                            why = readWriteDescriptor.doWrite()
            except BaseException:
                why = sys.exc_info()[1]
                log.err()
            if why:
                self._disconnectSelectable(readWriteDescriptor, why, isRead)

        log.callWithLogger(readWriteDescriptor, _drdw)
Exemple #3
0
 def unregister(self, fileobj):
     del self._mappings[fileobj]
     source = self._registered_fds.pop(fileobj).cf_source
     CFRunLoopRemoveSource(self._runloop, source, kCFRunLoopCommonModes)