Index: Lib/test/test_socket.py =================================================================== --- Lib/test/test_socket.py (Revision 58923) +++ Lib/test/test_socket.py (Arbeitskopie) @@ -558,7 +558,7 @@ def testFromFd(self): # Testing fromfd() if not hasattr(socket, "fromfd"): - return # On Windows, this doesn't exist + return # On BeOS, OS/2 and RiscOS this doesn't exist fd = self.cli_conn.fileno() sock = socket.fromfd(fd, socket.AF_INET, socket.SOCK_STREAM) msg = sock.recv(1024) @@ -567,6 +567,27 @@ 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 testInnerDup(self): + # Testing dup() for the wrapped socket object + inner = self.cli_conn._sock + if not hasattr(inner, "dup"): + return # On BeOS, OS/2 and RiscOS this doesn't exist + sock = inner.dup() + msg = sock.recv(1024) + self.assertEqual(msg, MSG) + + def _testInnerDup(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 58923) +++ Modules/socketmodule.c (Arbeitskopie) @@ -336,11 +336,32 @@ #include "getnameinfo.c" #endif -#if defined(MS_WINDOWS) || defined(__BEOS__) +#ifdef MS_WINDOWS +/* On Windows a socket is really a handle not an fd */ +static SOCKET +duplicate_socket(SOCKET handle) +{ + HANDLE newhandle; + + if (!DuplicateHandle(GetCurrentProcess(), (HANDLE)handle, + GetCurrentProcess(), &newhandle, + 0, FALSE, DUPLICATE_SAME_ACCESS)) + { + WSASetLastError(WSAEBADF); + return INVALID_SOCKET; + } + return (SOCKET)newhandle; +} +#define dup(fd) duplicate_socket(fd) +#define SOCKETCLOSE closesocket +#define NO_MAKEFILE /* socket handles can't be treated like file handles */ +#endif + +#ifdef __BEOS__ /* BeOS suffers from the same socket dichotomy as Win32... - [cjh] */ /* seem to be a few differences in the API */ #define SOCKETCLOSE closesocket -#define NO_DUP /* Actually it exists on NT 3.5, but what the heck... */ +#define NO_DUP #endif #ifdef MS_WIN32 @@ -357,6 +378,10 @@ #define SOCKETCLOSE close #endif +#ifdef NO_DUP +#define NO_MAKEFILE +#endif + #if defined(HAVE_BLUETOOTH_H) || defined(HAVE_BLUETOOTH_BLUETOOTH_H) #define USE_BLUETOOTH 1 #if defined(__FreeBSD__) @@ -2068,7 +2093,11 @@ PyObject *sock; newfd = dup(s->sock_fd); +#ifdef MS_WINDOWS + if (newfd == INVALID_SOCKET) +#else if (newfd < 0) +#endif return s->errorhandler(); sock = (PyObject *) new_sockobject(newfd, s->sock_family, @@ -2176,7 +2205,7 @@ will allow before refusing new connections."); -#ifndef NO_DUP +#ifndef NO_MAKEFILE /* s.makefile(mode) method. Create a new open file object referring to a dupped version of the socket's file descriptor. (The dup() call is necessary so @@ -2237,7 +2266,7 @@ Return a regular file object corresponding to the socket.\n\ The mode and buffersize arguments are as for the built-in open() function."); -#endif /* NO_DUP */ +#endif /* NO_MAKEFILE */ /* * This is the guts of the recv() and recv_into() methods, which reads into a @@ -2791,7 +2820,7 @@ getsockopt_doc}, {"listen", (PyCFunction)sock_listen, METH_O, listen_doc}, -#ifndef NO_DUP +#ifndef NO_MAKEFILE {"makefile", (PyCFunction)sock_makefile, METH_VARARGS, makefile_doc}, #endif @@ -3481,7 +3510,11 @@ return NULL; /* Dup the fd so it and the socket can be closed independently */ fd = dup(fd); +#ifdef MS_WINDOWS + if (fd == INVALID_SOCKET) +#else if (fd < 0) +#endif return set_error(); s = new_sockobject(fd, family, type, proto); return (PyObject *) s;