[CalendarServer-changes] [12104] twext/trunk/twext

source_changes at macosforge.org source_changes at macosforge.org
Wed Mar 12 11:23:14 PDT 2014


Revision: 12104
          http://trac.calendarserver.org//changeset/12104
Author:   wsanchez at apple.com
Date:     2013-12-13 20:18:37 -0800 (Fri, 13 Dec 2013)
Log Message:
-----------
Get rid of sendmsg; twisted has it

Modified Paths:
--------------
    twext/trunk/twext/internet/sendfdport.py
    twext/trunk/twext/internet/test/test_fswatch.py
    twext/trunk/twext/python/sendfd.py

Removed Paths:
-------------
    twext/trunk/twext/python/sendmsg.c
    twext/trunk/twext/python/test/test_sendmsg.py

Modified: twext/trunk/twext/internet/sendfdport.py
===================================================================
--- twext/trunk/twext/internet/sendfdport.py	2013-12-14 04:04:50 UTC (rev 12103)
+++ twext/trunk/twext/internet/sendfdport.py	2013-12-14 04:18:37 UTC (rev 12104)
@@ -16,24 +16,24 @@
 ##
 
 """
-Implementation of a TCP/SSL port that uses sendmsg/recvmsg as implemented by
-L{twext.python.sendfd}.
+Implementation of a TCP/SSL port that uses send1msg/recv1msg as implemented by
+L{twisted.python.sendfd}.
 """
 
 from os import close
 from errno import EAGAIN, ENOBUFS
-from socket import (socketpair, fromfd, error as SocketError, AF_UNIX,
-                    SOCK_STREAM, SOCK_DGRAM)
+from socket import (
+    socketpair, fromfd, error as SocketError, AF_UNIX, SOCK_STREAM, SOCK_DGRAM
+)
 
 from zope.interface import Interface
 
+from twisted.python.sendmsg import send1msg, recv1msg, getsockfam
 from twisted.internet.abstract import FileDescriptor
 from twisted.internet.protocol import Protocol, Factory
 
 from twext.python.log import Logger
-from twext.python.sendmsg import sendmsg, recvmsg
 from twext.python.sendfd import sendfd, recvfd
-from twext.python.sendmsg import getsockfam
 
 log = Logger()
 
@@ -94,7 +94,7 @@
     A socket in the master process pointing at a file descriptor that can be
     used to transmit sockets to a subprocess.
 
-    @ivar outSocket: the UNIX socket used as the sendmsg() transport.
+    @ivar outSocket: the UNIX socket used as the send1msg() transport.
     @type outSocket: L{socket.socket}
 
     @ivar outgoingSocketQueue: an outgoing queue of sockets to send to the
@@ -104,10 +104,11 @@
     @ivar outgoingSocketQueue: a C{list} of 2-tuples of C{(socket-object,
         bytes)}
 
-    @ivar status: a record of the last status message received (via recvmsg)
-        from the subprocess: this is an application-specific indication of how
-        ready this subprocess is to receive more connections.  A typical usage
-        would be to count the open connections: this is what is passed to
+    @ivar status: a record of the last status message received (via
+        L{recv1msg}) from the subprocess: this is an application-specific
+        indication of how ready this subprocess is to receive more connections.
+        A typical usage would be to count the open connections: this is what is
+        passed to
     @type status: See L{IStatusWatcher} for an explanation of which methods
         determine this type.
 
@@ -134,12 +135,14 @@
         self.startWriting()
 
 
-    def doRead(self, recvmsg=recvmsg):
+    def doRead(self, recvmsg=recv1msg):
         """
         Receive a status / health message and record it.
         """
         try:
-            data, _ignore_flags, _ignore_ancillary = recvmsg(self.outSocket.fileno())
+            data, _ignore_flags, _ignore_ancillary = recvmsg(
+                self.outSocket.fileno()
+            )
         except SocketError, se:
             if se.errno not in (EAGAIN, ENOBUFS):
                 raise
@@ -198,7 +201,7 @@
         than the somewhat more abstract language that would be accurate.
     """
 
-    def initialStatus(): #@NoSelf
+    def initialStatus():
         """
         A new socket was created and added to the dispatcher.  Compute an
         initial value for its status.
@@ -207,7 +210,7 @@
         """
 
 
-    def newConnectionStatus(previousStatus): #@NoSelf
+    def newConnectionStatus(previousStatus):
         """
         A new connection was sent to a given socket.  Compute its status based
         on the previous status of that socket.
@@ -219,7 +222,7 @@
         """
 
 
-    def statusFromMessage(previousStatus, message): #@NoSelf
+    def statusFromMessage(previousStatus, message):
         """
         A status message was received by a worker.  Convert the previous status
         value (returned from L{newConnectionStatus}, L{initialStatus}, or
@@ -233,7 +236,7 @@
         """
 
 
-    def closeCountFromStatus(previousStatus): #@NoSelf
+    def closeCountFromStatus(previousStatus):
         """
         Based on a status previously returned from a method on this
         L{IStatusWatcher}, determine how many sockets may be closed.
@@ -332,7 +335,7 @@
 
     def addSocket(self, socketpair=lambda: socketpair(AF_UNIX, SOCK_DGRAM)):
         """
-        Add a C{sendmsg()}-oriented AF_UNIX socket to the pool of sockets being
+        Add a L{send1msg}-oriented AF_UNIX socket to the pool of sockets being
         used for transmitting file descriptors to child processes.
 
         @return: a socket object for the receiving side; pass this object's
@@ -367,13 +370,13 @@
     """
     An L{InheritedPort} is an L{IReadDescriptor}/L{IWriteDescriptor} created in
     the I{worker process} to handle incoming connections dispatched via
-    C{sendmsg}.
+    L{send1msg}.
     """
 
     def __init__(self, fd, transportFactory, protocolFactory):
         """
         @param fd: the file descriptor representing a UNIX socket connected to
-            a I{master process}.  We will call C{recvmsg} on this socket to
+            a I{master process}.  We will call L{recv1msg} on this socket to
             receive file descriptors.
         @type fd: C{int}
 
@@ -434,7 +437,7 @@
         while self.statusQueue:
             msg = self.statusQueue.pop(0)
             try:
-                sendmsg(self.fd, msg, 0)
+                send1msg(self.fd, msg, 0)
             except SocketError, se:
                 if se.errno in (EAGAIN, ENOBUFS):
                     self.statusQueue.insert(0, msg)

Modified: twext/trunk/twext/internet/test/test_fswatch.py
===================================================================
--- twext/trunk/twext/internet/test/test_fswatch.py	2013-12-14 04:04:50 UTC (rev 12103)
+++ twext/trunk/twext/internet/test/test_fswatch.py	2013-12-14 04:18:37 UTC (rev 12104)
@@ -18,8 +18,9 @@
 Tests for L{twext.internet.fswatch}.
 """
 
-from twext.internet.fswatch import DirectoryChangeListener, patchReactor, \
-    IDirectoryChangeListenee
+from twext.internet.fswatch import (
+    DirectoryChangeListener, patchReactor, IDirectoryChangeListenee
+)
 from twisted.internet.kqreactor import KQueueReactor
 from twisted.python.filepath import FilePath
 from twisted.trial.unittest import TestCase

Modified: twext/trunk/twext/python/sendfd.py
===================================================================
--- twext/trunk/twext/python/sendfd.py	2013-12-14 04:04:50 UTC (rev 12103)
+++ twext/trunk/twext/python/sendfd.py	2013-12-14 04:18:37 UTC (rev 12104)
@@ -18,15 +18,17 @@
 from struct import pack, unpack, calcsize
 from socket import SOL_SOCKET
 
-from twext.python.sendmsg import sendmsg, recvmsg, SCM_RIGHTS
+from twisted.python.sendmsg import send1msg, recv1msg, SCM_RIGHTS
 
+
+
 def sendfd(socketfd, fd, description):
     """
-    Send the given FD to another process via L{sendmsg} on the given C{AF_UNIX}
-    socket.
+    Send the given FD to another process via L{send1msg} on the given
+    C{AF_UNIX} socket.
 
     @param socketfd: An C{AF_UNIX} socket, attached to another process waiting
-        to receive sockets via the ancillary data mechanism in L{sendmsg}.
+        to receive sockets via the ancillary data mechanism in L{send1msg}.
 
     @type socketfd: C{int}
 
@@ -38,7 +40,7 @@
 
     @type description: C{str}
     """
-    sendmsg(
+    send1msg(
         socketfd, description, 0, [(SOL_SOCKET, SCM_RIGHTS, pack("i", fd))]
     )
 
@@ -46,11 +48,11 @@
 
 def recvfd(socketfd):
     """
-    Receive a file descriptor from a L{sendmsg} message on the given C{AF_UNIX}
-    socket.
+    Receive a file descriptor from a L{send1msg} message on the given
+    C{AF_UNIX} socket.
 
     @param socketfd: An C{AF_UNIX} socket, attached to another process waiting
-        to send sockets via the ancillary data mechanism in L{sendmsg}.
+        to send sockets via the ancillary data mechanism in L{send1msg}.
 
     @param fd: C{int}
 
@@ -58,15 +60,18 @@
 
     @rtype: 2-tuple of (C{int}, C{str})
     """
-    data, _ignore_flags, ancillary = recvmsg(socketfd)
+    data, _ignore_flags, ancillary = recv1msg(socketfd)
     [(_ignore_cmsg_level, _ignore_cmsg_type, packedFD)] = ancillary
+
     # cmsg_level and cmsg_type really need to be SOL_SOCKET / SCM_RIGHTS, but
     # since those are the *only* standard values, there's not much point in
     # checking.
     unpackedFD = 0
     int_size = calcsize("i")
-    if len(packedFD) > int_size:       # [ar]happens on 64 bit architecture (FreeBSD)
+
+    if len(packedFD) > int_size:       # [ar]happens on 64 bit arch (FreeBSD)
         [unpackedFD] = unpack("i", packedFD[0:int_size])
     else:
         [unpackedFD] = unpack("i", packedFD)
+
     return (unpackedFD, data)

Deleted: twext/trunk/twext/python/sendmsg.c
===================================================================
--- twext/trunk/twext/python/sendmsg.c	2013-12-14 04:04:50 UTC (rev 12103)
+++ twext/trunk/twext/python/sendmsg.c	2013-12-14 04:18:37 UTC (rev 12104)
@@ -1,423 +0,0 @@
-/*
- * Copyright (c) 2010-2013 Apple Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define PY_SSIZE_T_CLEAN 1
-#include <Python.h>
-
-#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
-/* This may cause some warnings, but if you want to get rid of them, upgrade
- * your Python version.  */
-typedef int Py_ssize_t;
-#endif
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <signal.h>
-
-/*
- * As per
- * <http://pubs.opengroup.org/onlinepubs/007904875/basedefs/sys/socket.h.html
- * #tag_13_61_05>:
- *
- *     "To forestall portability problems, it is recommended that applications
- *     not use values larger than (2**31)-1 for the socklen_t type."
- */
-
-#define SOCKLEN_MAX 0x7FFFFFFF
-
-PyObject *sendmsg_socket_error;
-
-static PyObject *sendmsg_sendmsg(PyObject *self, PyObject *args, PyObject *keywds);
-static PyObject *sendmsg_recvmsg(PyObject *self, PyObject *args, PyObject *keywds);
-static PyObject *sendmsg_getsockfam(PyObject *self, PyObject *args, PyObject *keywds);
-
-static PyMethodDef sendmsg_methods[] = {
-    {"sendmsg", (PyCFunction) sendmsg_sendmsg, METH_VARARGS | METH_KEYWORDS,
-     NULL},
-    {"recvmsg", (PyCFunction) sendmsg_recvmsg, METH_VARARGS | METH_KEYWORDS,
-     NULL},
-    {"getsockfam", (PyCFunction) sendmsg_getsockfam,
-     METH_VARARGS | METH_KEYWORDS, NULL},
-    {NULL, NULL, 0, NULL}
-};
-
-
-PyMODINIT_FUNC initsendmsg(void) {
-    PyObject *module;
-
-    sendmsg_socket_error = NULL; /* Make sure that this has a known value
-                                    before doing anything that might exit. */
-
-    module = Py_InitModule("sendmsg", sendmsg_methods);
-
-    if (!module) {
-        return;
-    }
-
-    /*
-      The following is the only value mentioned by POSIX:
-      http://www.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html
-    */
-
-    if (-1 == PyModule_AddIntConstant(module, "SCM_RIGHTS", SCM_RIGHTS)) {
-        return;
-    }
-
-
-    /* BSD, Darwin, Hurd */
-#if defined(SCM_CREDS)
-    if (-1 == PyModule_AddIntConstant(module, "SCM_CREDS", SCM_CREDS)) {
-        return;
-    }
-#endif
-
-    /* Linux */
-#if defined(SCM_CREDENTIALS)
-    if (-1 == PyModule_AddIntConstant(module, "SCM_CREDENTIALS", SCM_CREDENTIALS)) {
-        return;
-    }
-#endif
-
-    /* Apparently everywhere, but not standardized. */
-#if defined(SCM_TIMESTAMP)
-    if (-1 == PyModule_AddIntConstant(module, "SCM_TIMESTAMP", SCM_TIMESTAMP)) {
-        return;
-    }
-#endif
-
-    module = PyImport_ImportModule("socket");
-    if (!module) {
-        return;
-    }
-
-    sendmsg_socket_error = PyObject_GetAttrString(module, "error");
-    if (!sendmsg_socket_error) {
-        return;
-    }
-}
-
-static PyObject *sendmsg_sendmsg(PyObject *self, PyObject *args, PyObject *keywds) {
-
-    int fd;
-    int flags = 0;
-    Py_ssize_t sendmsg_result, iovec_length;
-    struct msghdr message_header;
-    struct iovec iov[1];
-    PyObject *ancillary = NULL;
-    PyObject *ultimate_result = NULL;
-    static char *kwlist[] = {"fd", "data", "flags", "ancillary", NULL};
-
-    if (!PyArg_ParseTupleAndKeywords(
-            args, keywds, "it#|iO:sendmsg", kwlist,
-            &fd,
-            &iov[0].iov_base,
-            &iovec_length,
-            &flags,
-            &ancillary)) {
-        return NULL;
-    }
-
-    iov[0].iov_len = iovec_length;
-
-    message_header.msg_name = NULL;
-    message_header.msg_namelen = 0;
-
-    message_header.msg_iov = iov;
-    message_header.msg_iovlen = 1;
-
-    message_header.msg_control = NULL;
-    message_header.msg_controllen = 0;
-
-    message_header.msg_flags = 0;
-
-    if (ancillary) {
-
-        if (!PyList_Check(ancillary)) {
-            PyErr_Format(PyExc_TypeError,
-                         "sendmsg argument 3 expected list, got %s",
-                         ancillary->ob_type->tp_name);
-            goto finished;
-        }
-
-        PyObject *iterator = PyObject_GetIter(ancillary);
-        PyObject *item = NULL;
-
-        if (iterator == NULL) {
-            goto finished;
-        }
-
-        size_t all_data_len = 0;
-
-        /* First we need to know how big the buffer needs to be in order to
-           have enough space for all of the messages. */
-        while ( (item = PyIter_Next(iterator)) ) {
-            int type, level;
-            Py_ssize_t data_len;
-            size_t prev_all_data_len;
-            char *data;
-            if (!PyArg_ParseTuple(
-                        item, "iit#:sendmsg ancillary data (level, type, data)",
-                        &level, &type, &data, &data_len)) {
-                Py_DECREF(item);
-                Py_DECREF(iterator);
-                goto finished;
-            }
-
-            prev_all_data_len = all_data_len;
-            all_data_len += CMSG_SPACE(data_len);
-
-            Py_DECREF(item);
-
-            if (all_data_len < prev_all_data_len) {
-                Py_DECREF(iterator);
-                PyErr_Format(PyExc_OverflowError,
-                             "Too much msg_control to fit in a size_t: %zu",
-                             prev_all_data_len);
-                goto finished;
-            }
-        }
-
-        Py_DECREF(iterator);
-        iterator = NULL;
-
-        /* Allocate the buffer for all of the ancillary elements, if we have
-         * any.  */
-        if (all_data_len) {
-            if (all_data_len > SOCKLEN_MAX) {
-                PyErr_Format(PyExc_OverflowError,
-                             "Too much msg_control to fit in a socklen_t: %zu",
-                             all_data_len);
-                goto finished;
-            }
-            message_header.msg_control = malloc(all_data_len);
-            if (!message_header.msg_control) {
-                PyErr_NoMemory();
-                goto finished;
-            }
-        }
-        message_header.msg_controllen = (socklen_t) all_data_len;
-
-        iterator = PyObject_GetIter(ancillary); /* again */
-        item = NULL;
-
-        if (!iterator) {
-            goto finished;
-        }
-
-        /* Unpack the tuples into the control message. */
-        struct cmsghdr *control_message = CMSG_FIRSTHDR(&message_header);
-        while ( (item = PyIter_Next(iterator)) ) {
-            int type, level;
-            Py_ssize_t data_len;
-            size_t data_size;
-            unsigned char *data, *cmsg_data;
-
-            /* We explicitly allocated enough space for all ancillary data
-               above; if there isn't enough room, all bets are off. */
-            assert(control_message);
-
-            if (!PyArg_ParseTuple(item,
-                                  "iit#:sendmsg ancillary data (level, type, data)",
-                                  &level,
-                                  &type,
-                                  &data,
-                                  &data_len)) {
-                Py_DECREF(item);
-                Py_DECREF(iterator);
-                goto finished;
-            }
-
-            control_message->cmsg_level = level;
-            control_message->cmsg_type = type;
-            data_size = CMSG_LEN(data_len);
-
-            if (data_size > SOCKLEN_MAX) {
-                Py_DECREF(item);
-                Py_DECREF(iterator);
-                PyErr_Format(PyExc_OverflowError,
-                             "CMSG_LEN(%zd) > SOCKLEN_MAX", data_len);
-                goto finished;
-            }
-
-            control_message->cmsg_len = (socklen_t) data_size;
-
-            cmsg_data = CMSG_DATA(control_message);
-            memcpy(cmsg_data, data, data_len);
-
-            Py_DECREF(item);
-
-            control_message = CMSG_NXTHDR(&message_header, control_message);
-        }
-
-        Py_DECREF(iterator);
-
-        if (PyErr_Occurred()) {
-            goto finished;
-        }
-    }
-
-    sendmsg_result = sendmsg(fd, &message_header, flags);
-
-    if (sendmsg_result < 0) {
-        PyErr_SetFromErrno(sendmsg_socket_error);
-        goto finished;
-    } else {
-        ultimate_result = Py_BuildValue("n", sendmsg_result);
-    }
-
-  finished:
-    if (message_header.msg_control) {
-        free(message_header.msg_control);
-    }
-    return ultimate_result;
-}
-
-static PyObject *sendmsg_recvmsg(PyObject *self, PyObject *args, PyObject *keywds) {
-    int fd = -1;
-    int flags = 0;
-    int maxsize = 8192;
-    int cmsg_size = 4*1024;
-    size_t cmsg_space;
-    Py_ssize_t recvmsg_result;
-
-    struct msghdr message_header;
-    struct cmsghdr *control_message;
-    struct iovec iov[1];
-    char *cmsgbuf;
-    PyObject *ancillary;
-    PyObject *final_result = NULL;
-
-    static char *kwlist[] = {"fd", "flags", "maxsize", "cmsg_size", NULL};
-
-    if (!PyArg_ParseTupleAndKeywords(args, keywds, "i|iii:recvmsg", kwlist,
-                                     &fd, &flags, &maxsize, &cmsg_size)) {
-        return NULL;
-    }
-
-    cmsg_space = CMSG_SPACE(cmsg_size);
-
-    /* overflow check */
-    if (cmsg_space > SOCKLEN_MAX) {
-        PyErr_Format(PyExc_OverflowError,
-                     "CMSG_SPACE(cmsg_size) greater than SOCKLEN_MAX: %d",
-                     cmsg_size);
-        return NULL;
-    }
-
-    message_header.msg_name = NULL;
-    message_header.msg_namelen = 0;
-
-    iov[0].iov_len = maxsize;
-    iov[0].iov_base = malloc(maxsize);
-
-    if (!iov[0].iov_base) {
-        PyErr_NoMemory();
-        return NULL;
-    }
-
-    message_header.msg_iov = iov;
-    message_header.msg_iovlen = 1;
-
-    cmsgbuf = malloc(cmsg_space);
-
-    if (!cmsgbuf) {
-        free(iov[0].iov_base);
-        PyErr_NoMemory();
-        return NULL;
-    }
-
-    memset(cmsgbuf, 0, cmsg_space);
-    message_header.msg_control = cmsgbuf;
-    /* see above for overflow check */
-    message_header.msg_controllen = (socklen_t) cmsg_space;
-
-    recvmsg_result = recvmsg(fd, &message_header, flags);
-    if (recvmsg_result < 0) {
-        PyErr_SetFromErrno(sendmsg_socket_error);
-        goto finished;
-    }
-
-    ancillary = PyList_New(0);
-    if (!ancillary) {
-        goto finished;
-    }
-
-    for (control_message = CMSG_FIRSTHDR(&message_header);
-         control_message;
-         control_message = CMSG_NXTHDR(&message_header,
-                                       control_message)) {
-        PyObject *entry;
-
-        /* Some platforms apparently always fill out the ancillary data
-           structure with a single bogus value if none is provided; ignore it,
-           if that is the case. */
-
-        if ((!(control_message->cmsg_level)) &&
-            (!(control_message->cmsg_type))) {
-            continue;
-        }
-
-        entry = Py_BuildValue(
-            "(iis#)",
-            control_message->cmsg_level,
-            control_message->cmsg_type,
-            CMSG_DATA(control_message),
-            (Py_ssize_t) (control_message->cmsg_len - sizeof(struct cmsghdr)));
-
-        if (!entry) {
-            Py_DECREF(ancillary);
-            goto finished;
-        }
-
-        if (PyList_Append(ancillary, entry) < 0) {
-            Py_DECREF(ancillary);
-            Py_DECREF(entry);
-            goto finished;
-        } else {
-            Py_DECREF(entry);
-        }
-    }
-
-    final_result = Py_BuildValue(
-        "s#iO",
-        iov[0].iov_base,
-        recvmsg_result,
-        message_header.msg_flags,
-        ancillary);
-
-    Py_DECREF(ancillary);
-
-  finished:
-    free(iov[0].iov_base);
-    free(cmsgbuf);
-    return final_result;
-}
-
-static PyObject *sendmsg_getsockfam(PyObject *self, PyObject *args,
-                                    PyObject *keywds) {
-    int fd;
-    struct sockaddr sa;
-    static char *kwlist[] = {"fd", NULL};
-    if (!PyArg_ParseTupleAndKeywords(args, keywds, "i", kwlist, &fd)) {
-        return NULL;
-    }
-    socklen_t sz = sizeof(sa);
-    if (getsockname(fd, &sa, &sz)) {
-        PyErr_SetFromErrno(sendmsg_socket_error);
-        return NULL;
-    }
-    return Py_BuildValue("i", sa.sa_family);
-}

Deleted: twext/trunk/twext/python/test/test_sendmsg.py
===================================================================
--- twext/trunk/twext/python/test/test_sendmsg.py	2013-12-14 04:04:50 UTC (rev 12103)
+++ twext/trunk/twext/python/test/test_sendmsg.py	2013-12-14 04:18:37 UTC (rev 12104)
@@ -1,172 +0,0 @@
-##
-# Copyright (c) 2010-2013 Apple Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##
-
-import socket
-from os import pipe, read, close, environ
-from twext.python.filepath import CachingFilePath as FilePath
-import sys
-
-from twisted.internet.defer import Deferred
-from twisted.internet.error import ProcessDone
-from twisted.trial.unittest import TestCase
-from twisted.internet.defer import inlineCallbacks
-from twisted.internet import reactor
-
-from twext.python.sendmsg import sendmsg, recvmsg
-from twext.python.sendfd import sendfd
-from twisted.internet.protocol import ProcessProtocol
-
-class ExitedWithStderr(Exception):
-    """
-    A process exited with some stderr.
-    """
-
-    def __str__(self):
-        """
-        Dump the errors in a pretty way in the event of a subprocess traceback.
-        """
-        return '\n'.join([''] + list(self.args))
-
-
-class StartStopProcessProtocol(ProcessProtocol):
-    """
-    An L{IProcessProtocol} with a Deferred for events where the subprocess
-    starts and stops.
-    """
-
-    def __init__(self):
-        self.started = Deferred()
-        self.stopped = Deferred()
-        self.output = ''
-        self.errors = ''
-
-    def connectionMade(self):
-        self.started.callback(self.transport)
-
-    def outReceived(self, data):
-        self.output += data
-
-    def errReceived(self, data):
-        self.errors += data
-
-    def processEnded(self, reason):
-        if reason.check(ProcessDone):
-            self.stopped.callback(self.output)
-        else:
-            self.stopped.errback(ExitedWithStderr(
-                    self.errors, self.output))
-
-
-
-def bootReactor():
-    """
-    Yield this from a trial test to bootstrap the reactor in order to avoid
-    PotentialZombieWarning, for tests that use subprocesses.  This hack will no
-    longer be necessary in Twisted 10.1, since U{the underlying bug was fixed
-    <http://twistedmatrix.com/trac/ticket/2078>}.
-    """
-    d = Deferred()
-    reactor.callLater(0, d.callback, None)
-    return d
-
-
-
-class SendmsgTestCase(TestCase):
-    """
-    Tests for sendmsg extension module and associated file-descriptor sending
-    functionality in L{twext.python.sendfd}.
-    """
-
-    def setUp(self):
-        """
-        Create a pair of UNIX sockets.
-        """
-        self.input, self.output = socket.socketpair(socket.AF_UNIX)
-
-
-    def tearDown(self):
-        """
-        Close the sockets opened by setUp.
-        """
-        self.input.close()
-        self.output.close()
-
-
-    def test_roundtrip(self):
-        """
-        L{recvmsg} will retrieve a message sent via L{sendmsg}.
-        """
-        sendmsg(self.input.fileno(), "hello, world!", 0)
-
-        result = recvmsg(fd=self.output.fileno())
-        self.assertEquals(result, ("hello, world!", 0, []))
-
-
-    def test_wrongTypeAncillary(self):
-        """
-        L{sendmsg} will show a helpful exception message when given the wrong
-        type of object for the 'ancillary' argument.
-        """
-        error = self.assertRaises(TypeError,
-                                  sendmsg, self.input.fileno(),
-                                  "hello, world!", 0, 4321)
-        self.assertEquals(str(error),
-                          "sendmsg argument 3 expected list, got int")
-
-
-    def spawn(self, script):
-        """
-        Start a script that is a peer of this test as a subprocess.
-
-        @param script: the module name of the script in this directory (no
-            package prefix, no '.py')
-        @type script: C{str}
-
-        @rtype: L{StartStopProcessProtocol}
-        """
-        sspp = StartStopProcessProtocol()
-        reactor.spawnProcess(
-            sspp, sys.executable, [
-                sys.executable,
-                FilePath(__file__).sibling(script + ".py").path,
-                str(self.output.fileno()),
-            ],
-            environ,
-            childFDs={0: "w", 1: "r", 2: "r",
-                      self.output.fileno(): self.output.fileno()}
-        )
-        return sspp
-
-
-    @inlineCallbacks
-    def test_sendSubProcessFD(self):
-        """
-        Calling L{sendsmsg} with SOL_SOCKET, SCM_RIGHTS, and a platform-endian
-        packed file descriptor number should send that file descriptor to a
-        different process, where it can be retrieved by using L{recvmsg}.
-        """
-        yield bootReactor()
-        sspp = self.spawn("pullpipe")
-        yield sspp.started
-        pipeOut, pipeIn = pipe()
-        self.addCleanup(close, pipeOut)
-        sendfd(self.input.fileno(), pipeIn, "blonk")
-        close(pipeIn)
-        yield sspp.stopped
-        self.assertEquals(read(pipeOut, 1024), "Test fixture data: blonk.\n")
-        # Make sure that the pipe is actually closed now.
-        self.assertEquals(read(pipeOut, 1024), "")
-
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20140312/795b4900/attachment.html>


More information about the calendarserver-changes mailing list