Christian Heimes added the comment:
Oh, I forgot
Added file: http://bugs.python.org/file8757/py3k_another_socket.patch
__________________________________
Tracker <[EMAIL PROTECTED]>
<http://bugs.python.org/issue1378>
__________________________________
Index: Include/longobject.h
===================================================================
--- Include/longobject.h (revision 58972)
+++ Include/longobject.h (working copy)
@@ -26,6 +26,15 @@
PyAPI_FUNC(unsigned long) PyLong_AsUnsignedLong(PyObject *);
PyAPI_FUNC(unsigned long) PyLong_AsUnsignedLongMask(PyObject *);
+/* Used by socketmodule.c */
+#if SIZEOF_SOCKET_T <= SIZEOF_LONG
+#define PyLong_FromSocket_t(fd) PyLong_FromLong((SOCKET_T)(fd))
+#define PyLong_AsSocket_t(fd) (SOCKET_T)PyLong_AsLong(fd)
+#else
+#define PyLong_FromSocket_t(fd) PyLong_FromLongLong(((SOCKET_T)(fd));
+#define PyLong_AsSocket_t(fd) (SOCKET_T)PyLong_AsLongLong(fd)
+#endif
+
/* For use by intobject.c only */
PyAPI_DATA(int) _PyLong_DigitValue[256];
Index: Lib/socket.py
===================================================================
--- Lib/socket.py (revision 58972)
+++ Lib/socket.py (working copy)
@@ -79,28 +79,14 @@
__all__.append("errorTab")
-# True if os.dup() can duplicate socket descriptors.
-# (On Windows at least, os.dup only works on files)
-_can_dup_socket = hasattr(_socket.socket, "dup")
-
-if _can_dup_socket:
- def fromfd(fd, family=AF_INET, type=SOCK_STREAM, proto=0):
- nfd = os.dup(fd)
- return socket(family, type, proto, fileno=nfd)
-
class socket(_socket.socket):
"""A subclass of _socket.socket adding the makefile() method."""
__slots__ = ["__weakref__", "_io_refs", "_closed"]
- if not _can_dup_socket:
- __slots__.append("_base")
def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None):
- if fileno is None:
- _socket.socket.__init__(self, family, type, proto)
- else:
- _socket.socket.__init__(self, family, type, proto, fileno)
+ _socket.socket.__init__(self, family, type, proto, fileno)
self._io_refs = 0
self._closed = False
@@ -114,23 +100,27 @@
s[7:])
return s
+ def dup(self):
+ """dup() -> socket object
+
+ Return a new socket object connected to the same system resource.
+ """
+ fd = self._dup()
+ return self.__class__(self.family, self.type, self.proto, fileno=fd)
+
def accept(self):
- """Wrap accept() to give the connection the right type."""
- conn, addr = _socket.socket.accept(self)
- fd = conn.fileno()
- nfd = fd
- if _can_dup_socket:
- nfd = os.dup(fd)
- wrapper = socket(self.family, self.type, self.proto, fileno=nfd)
- if fd == nfd:
- wrapper._base = conn # Keep the base alive
- else:
- conn.close()
- return wrapper, addr
+ """accept() -> (socket object, address info)
+ Wait for an incoming connection. Return a new socket
+ representing the connection, and the address of the client.
+ For IP sockets, the address info is a pair (hostaddr, port).
+ """
+ fd, addr = self._accept()
+ return socket(self.family, self.type, self.proto, fileno=fd), addr
+
def makefile(self, mode="r", buffering=None, *,
encoding=None, newline=None):
- """Return an I/O stream connected to the socket.
+ """makefile(...) -> an I/O stream connected to the socket
The arguments are as for io.open() after the filename,
except the only mode characters supported are 'r', 'w' and 'b'.
@@ -184,21 +174,8 @@
def close(self):
self._closed = True
- if self._io_refs < 1:
- self._real_close()
-
- # _real_close calls close on the _socket.socket base class.
-
- if not _can_dup_socket:
- def _real_close(self):
+ if self._io_refs <= 0:
_socket.socket.close(self)
- base = getattr(self, "_base", None)
- if base is not None:
- self._base = None
- base.close()
- else:
- def _real_close(self):
- _socket.socket.close(self)
class SocketIO(io.RawIOBase):
Index: Lib/test/test_socket.py
===================================================================
--- Lib/test/test_socket.py (revision 58972)
+++ Lib/test/test_socket.py (working copy)
@@ -575,6 +575,15 @@
def _testFromFd(self):
self.serv_conn.send(MSG)
+ def testDup(self):
+ # Testing dup()
+ sock = self.cli_conn.dup()
+ msg = sock.recv(1024)
+ self.assertEqual(msg, MSG)
+
+ def _testDup(self):
+ self.serv_conn.send(MSG)
+
def testShutdown(self):
# Testing shutdown()
msg = self.cli_conn.recv(1024)
Index: Modules/socketmodule.c
===================================================================
--- Modules/socketmodule.c (revision 58972)
+++ Modules/socketmodule.c (working copy)
@@ -19,6 +19,8 @@
a subclass of socket.error
- socket.herror: exception raised for gethostby* errors,
a subclass of socket.error
+- socket.fromfd(fd, family, type[, proto]) --> new socket object (created
+ from an existing file descriptor)
- socket.gethostbyname(hostname) --> host IP address (string: 'dd.dd.dd.dd')
- socket.gethostbyaddr(IP address) --> (hostname, [alias, ...], [IP addr, ...])
- socket.gethostname() --> host name (string: 'spam' or 'spam.domain.com')
@@ -89,12 +91,12 @@
\n\
Methods of socket objects (keyword arguments not allowed):\n\
\n\
-accept() -- accept a connection, returning new socket and client address\n\
+_accept() -- accept connection, returning new socket fd and client address\n\
bind(addr) -- bind the socket to a local address\n\
close() -- close the socket\n\
connect(addr) -- connect the socket to a remote address\n\
connect_ex(addr) -- connect, return an error code instead of an exception\n\
-dup() -- return a new socket object identical to the current one [*]\n\
+_dup() -- return a new socket fd duplicated from fileno()\n\
fileno() -- return underlying file descriptor\n\
getpeername() -- return remote address [*]\n\
getsockname() -- return local address\n\
@@ -324,10 +326,26 @@
#include "getnameinfo.c"
#endif
-#if defined(MS_WINDOWS)
-/* seem to be a few differences in the API */
+#ifdef MS_WINDOWS
+/* On Windows a socket is really a handle not an fd */
+static SOCKET
+dup_socket(SOCKET handle)
+{
+ HANDLE newhandle;
+
+ if (!DuplicateHandle(GetCurrentProcess(), (HANDLE)handle,
+ GetCurrentProcess(), &newhandle,
+ 0, FALSE, DUPLICATE_SAME_ACCESS))
+ {
+ WSASetLastError(GetLastError());
+ return INVALID_SOCKET;
+ }
+ return (SOCKET)newhandle;
+}
#define SOCKETCLOSE closesocket
-#define NO_DUP /* Actually it exists on NT 3.5, but what the heck... */
+#else
+/* On Unix we can use dup to duplicate the file descriptor of a socket*/
+#define dup_socket(fd) dup(fd)
#endif
#ifdef MS_WIN32
@@ -701,7 +719,7 @@
pollfd.events = writing ? POLLOUT : POLLIN;
/* s->sock_timeout is in seconds, timeout in ms */
- timeout = (int)(s->sock_timeout * 1000 + 0.5);
+ timeout = (int)(s->sock_timeout * 1000 + 0.5);
n = poll(&pollfd, 1, timeout);
}
#else
@@ -721,7 +739,7 @@
n = select(s->sock_fd+1, &fds, NULL, NULL, &tv);
}
#endif
-
+
if (n < 0)
return -1;
if (n == 0)
@@ -1496,7 +1514,7 @@
}
-/* s.accept() method */
+/* s._accept() -> (fd, address) */
static PyObject *
sock_accept(PySocketSockObject *s)
@@ -1530,17 +1548,12 @@
if (newfd == INVALID_SOCKET)
return s->errorhandler();
- /* Create the new object with unspecified family,
- to avoid calls to bind() etc. on it. */
- sock = (PyObject *) new_sockobject(newfd,
- s->sock_family,
- s->sock_type,
- s->sock_proto);
-
+ sock = PyLong_FromSocket_t(newfd);
if (sock == NULL) {
SOCKETCLOSE(newfd);
goto finally;
}
+
addr = makesockaddr(s->sock_fd, SAS2SA(&addrbuf),
addrlen, s->sock_proto);
if (addr == NULL)
@@ -1555,11 +1568,11 @@
}
PyDoc_STRVAR(accept_doc,
-"accept() -> (socket object, address info)\n\
+"_accept() -> (integer, address info)\n\
\n\
-Wait for an incoming connection. Return a new socket representing the\n\
-connection, and the address of the client. For IP sockets, the address\n\
-info is a pair (hostaddr, port).");
+Wait for an incoming connection. Return a new socket file descriptor\n\
+representing the connection, and the address of the client.\n\
+For IP sockets, the address info is a pair (hostaddr, port).");
/* s.setblocking(flag) method. Argument:
False -- non-blocking mode; same as settimeout(0)
@@ -1955,11 +1968,7 @@
static PyObject *
sock_fileno(PySocketSockObject *s)
{
-#if SIZEOF_SOCKET_T <= SIZEOF_LONG
- return PyInt_FromLong((long) s->sock_fd);
-#else
- return PyLong_FromLongLong((PY_LONG_LONG)s->sock_fd);
-#endif
+ return PyLong_FromSocket_t(s->sock_fd);
}
PyDoc_STRVAR(fileno_doc,
@@ -1969,7 +1978,7 @@
#ifndef NO_DUP
-/* s.dup() method */
+/* s._dup() method */
static PyObject *
sock_dup(PySocketSockObject *s)
@@ -1977,22 +1986,20 @@
SOCKET_T newfd;
PyObject *sock;
- newfd = dup(s->sock_fd);
- if (newfd < 0)
+ newfd = dup_socket(s->sock_fd);
+ if (newfd == INVALID_SOCKET) {
return s->errorhandler();
- sock = (PyObject *) new_sockobject(newfd,
- s->sock_family,
- s->sock_type,
- s->sock_proto);
+ }
+ sock = PyLong_FromSocket_t(newfd);
if (sock == NULL)
SOCKETCLOSE(newfd);
return sock;
}
PyDoc_STRVAR(dup_doc,
-"dup() -> socket object\n\
+"_dup() -> integer\n\
\n\
-Return a new socket object connected to the same system resource.");
+Return a new socket file descriptor connected to the same system resource.");
#endif
@@ -2615,7 +2622,7 @@
/* List of methods for socket objects */
static PyMethodDef sock_methods[] = {
- {"accept", (PyCFunction)sock_accept, METH_NOARGS,
+ {"_accept", (PyCFunction)sock_accept, METH_NOARGS,
accept_doc},
{"bind", (PyCFunction)sock_bind, METH_O,
bind_doc},
@@ -2626,7 +2633,7 @@
{"connect_ex", (PyCFunction)sock_connect_ex, METH_O,
connect_ex_doc},
#ifndef NO_DUP
- {"dup", (PyCFunction)sock_dup, METH_NOARGS,
+ {"_dup", (PyCFunction)sock_dup, METH_NOARGS,
dup_doc},
#endif
{"fileno", (PyCFunction)sock_fileno, METH_NOARGS,
@@ -2745,8 +2752,8 @@
&family, &type, &proto, &fdobj))
return -1;
- if (fdobj != NULL) {
- fd = PyLong_AsLongLong(fdobj);
+ if (fdobj != NULL && fdobj != Py_None) {
+ fd = PyLong_AsSocket_t(fdobj);
if (fd == (SOCKET_T)(-1) && PyErr_Occurred())
return -1;
if (fd == INVALID_SOCKET) {
@@ -3245,6 +3252,39 @@
Return the protocol number for the named protocol. (Rarely used.)");
+#ifndef NO_DUP
+/* Create a socket object from a numeric file description.
+ Useful e.g. if stdin is a socket.
+ Additional arguments as for socket(). */
+
+/*ARGSUSED*/
+static PyObject *
+socket_fromfd(PyObject *self, PyObject *args)
+{
+ PySocketSockObject *s;
+ SOCKET_T fd, newfd;
+ int family, type, proto = 0;
+ if (!PyArg_ParseTuple(args, "iii|i:fromfd",
+ &fd, &family, &type, &proto))
+ return NULL;
+ /* Dup the fd so it and the socket can be closed independently */
+ newfd = dup_socket(fd);
+ if (newfd == INVALID_SOCKET)
+ return set_error();
+ s = new_sockobject(newfd, family, type, proto);
+ return (PyObject *) s;
+}
+
+PyDoc_STRVAR(fromfd_doc,
+"fromfd(fd, family, type[, proto]) -> socket object\n\
+\n\
+Create a socket object from a duplicate of the given\n\
+file descriptor.\n\
+The remaining arguments are the same as for socket().");
+
+#endif /* NO_DUP */
+
+
#ifdef HAVE_SOCKETPAIR
/* Create a pair of sockets using the socketpair() function.
Arguments as for socket() except the default family is AF_UNIX if
@@ -3884,6 +3924,10 @@
METH_VARARGS, getservbyport_doc},
{"getprotobyname", socket_getprotobyname,
METH_VARARGS, getprotobyname_doc},
+#ifndef NO_DUP
+ {"fromfd", socket_fromfd,
+ METH_VARARGS, fromfd_doc},
+#endif
#ifdef HAVE_SOCKETPAIR
{"socketpair", socket_socketpair,
METH_VARARGS, socketpair_doc},
@@ -4178,7 +4222,7 @@
PyModule_AddIntConstant(m, "NETLINK_IP6_FW", NETLINK_IP6_FW);
#ifdef NETLINK_DNRTMSG
PyModule_AddIntConstant(m, "NETLINK_DNRTMSG", NETLINK_DNRTMSG);
-#endif
+#endif
#ifdef NETLINK_TAPBASE
PyModule_AddIntConstant(m, "NETLINK_TAPBASE", NETLINK_TAPBASE);
#endif
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com