Change 23200 by [EMAIL PROTECTED] on 2004/08/06 12:55:31
Fix [perl #24269] socket() call uses non-IFS providers
causing subsequent print/read to hang or misbehave
Patch supplied by Artiom Morozov <[EMAIL PROTECTED]>
in the bug report at http://rt.perl.org/rt3/index.html?q=24269
Affected files ...
... //depot/perl/README.win32#75 edit
... //depot/perl/win32/Makefile#248 edit
... //depot/perl/win32/makefile.mk#276 edit
... //depot/perl/win32/win32.c#237 edit
... //depot/perl/win32/win32.h#111 edit
... //depot/perl/win32/win32sck.c#42 edit
Differences ...
==== //depot/perl/README.win32#75 (text) ====
Index: perl/README.win32
--- perl/README.win32#74~23172~ Fri Jul 30 07:31:08 2004
+++ perl/README.win32 Fri Aug 6 05:55:31 2004
@@ -739,6 +739,12 @@
Most C<socket()> related calls are supported, but they may not
behave as on Unix platforms. See L<perlport> for the full list.
+Perl requires Winsock2 to be installed on the system. If you're
+running Win95, you can download Winsock upgrade from here:
+
+http://www.microsoft.com/windows95/downloads/contents/WUAdminTools/S_WUNetworkingTools/W95Sockets2/Default.asp
+
+Later OS versions already include Winsock2 support.
Signal handling may not behave as on Unix platforms (where it
doesn't exactly "behave", either :). For instance, calling C<die()>
==== //depot/perl/win32/Makefile#248 (text) ====
Index: perl/win32/Makefile
--- perl/win32/Makefile#247~22887~ Tue Jun 1 07:30:48 2004
+++ perl/win32/Makefile Fri Aug 6 05:55:31 2004
@@ -303,7 +303,7 @@
# VC 6.0 can load the socket dll on demand. Makes the test suite
# run in about 10% less time.
-DELAYLOAD = -DELAYLOAD:wsock32.dll -DELAYLOAD:shell32.dll delayimp.lib
+DELAYLOAD = -DELAYLOAD:ws2_32.dll -DELAYLOAD:shell32.dll delayimp.lib
!ENDIF
ARCHDIR = ..\lib\$(ARCHNAME)
@@ -389,7 +389,7 @@
LIBBASEFILES = $(CRYPT_LIB) \
oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib \
comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib \
- netapi32.lib uuid.lib wsock32.lib mpr.lib winmm.lib \
+ netapi32.lib uuid.lib ws2_32.lib mpr.lib winmm.lib \
version.lib
# win64 doesn't have some libs
==== //depot/perl/win32/makefile.mk#276 (text) ====
Index: perl/win32/makefile.mk
--- perl/win32/makefile.mk#275~22901~ Thu Jun 3 08:19:52 2004
+++ perl/win32/makefile.mk Fri Aug 6 05:55:31 2004
@@ -290,7 +290,7 @@
# VC 6.0 can load the socket dll on demand. Makes the test suite
# run in about 10% less time.
-DELAYLOAD *= -DELAYLOAD:wsock32.dll -DELAYLOAD:shell32.dll delayimp.lib
+DELAYLOAD *= -DELAYLOAD:ws2_32.dll -DELAYLOAD:shell32.dll delayimp.lib
.IF "$(CFG)" == "Debug"
.ELSE
@@ -400,7 +400,7 @@
LIBFILES = $(CRYPT_LIB) $(LIBC) \
-lmoldname -lkernel32 -luser32 -lgdi32 \
-lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 \
- -loleaut32 -lnetapi32 -luuid -lwsock32 -lmpr \
+ -loleaut32 -lnetapi32 -luuid -lws2_32 -lmpr \
-lwinmm -lversion -lodbc32
.IF "$(CFG)" == "Debug"
@@ -484,7 +484,7 @@
LIBBASEFILES = $(CRYPT_LIB) \
oldnames.lib kernel32.lib user32.lib gdi32.lib winspool.lib \
comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib \
- netapi32.lib uuid.lib wsock32.lib mpr.lib winmm.lib \
+ netapi32.lib uuid.lib ws2_32.lib mpr.lib winmm.lib \
version.lib
# win64 doesn't have some libs
==== //depot/perl/win32/win32.c#237 (text) ====
Index: perl/win32/win32.c
--- perl/win32/win32.c#236~23128~ Fri Jul 16 05:16:05 2004
+++ perl/win32/win32.c Fri Aug 6 05:55:31 2004
@@ -5113,7 +5113,6 @@
New(1313, w32_pseudo_children, 1, child_tab);
w32_num_pseudo_children = 0;
# endif
- w32_init_socktype = 0;
w32_timerid = 0;
w32_poll_count = 0;
for (i=0; i < SIG_SIZE; i++) {
@@ -5167,7 +5166,6 @@
Newz(1313, dst->children, 1, child_tab);
dst->pseudo_id = 0;
Newz(1313, dst->pseudo_children, 1, child_tab);
- dst->thr_intern.Winit_socktype = 0;
dst->timerid = 0;
dst->poll_count = 0;
Copy(src->sigtable,dst->sigtable,SIG_SIZE,Sighandler_t);
==== //depot/perl/win32/win32.h#111 (text) ====
Index: perl/win32/win32.h
--- perl/win32/win32.h#110~21619~ Sun Nov 2 10:07:30 2003
+++ perl/win32/win32.h Fri Aug 6 05:55:31 2004
@@ -358,9 +358,6 @@
char Wstrerror_buffer[512];
struct servent Wservent;
char Wgetlogin_buffer[128];
-# ifdef USE_SOCKETS_AS_HANDLES
- int Winit_socktype;
-# endif
# ifdef HAVE_DES_FCRYPT
char Wcrypt_buffer[30];
# endif
@@ -427,7 +424,6 @@
#define w32_getlogin_buffer (PL_sys_intern.thr_intern.Wgetlogin_buffer)
#define w32_crypt_buffer (PL_sys_intern.thr_intern.Wcrypt_buffer)
#define w32_servent (PL_sys_intern.thr_intern.Wservent)
-#define w32_init_socktype (PL_sys_intern.thr_intern.Winit_socktype)
#define w32_use_showwindow (PL_sys_intern.thr_intern.Wuse_showwindow)
#define w32_showwindow (PL_sys_intern.thr_intern.Wshowwindow)
==== //depot/perl/win32/win32sck.c#42 (text) ====
Index: perl/win32/win32sck.c
--- perl/win32/win32sck.c#41~21989~ Sun Dec 28 03:49:20 2003
+++ perl/win32/win32sck.c Fri Aug 6 05:55:31 2004
@@ -16,6 +16,8 @@
#define Win32_Winsock
#endif
#include <windows.h>
+#include <ws2spi.h>
+
#include "EXTERN.h"
#include "perl.h"
@@ -86,11 +88,11 @@
* initalize the winsock interface and insure that it is
* cleaned up at exit.
*/
- version = 0x101;
+ version = 0x2;
if(ret = WSAStartup(version, &retdata))
Perl_croak_nocontext("Unable to locate winsock library!\n");
if(retdata.wVersion != version)
- Perl_croak_nocontext("Could not find version 1.1 of winsock dll\n");
+ Perl_croak_nocontext("Could not find version 2.0 of winsock dll\n");
/* atexit((void (*)(void)) EndSockets); */
wsock_started = 1;
@@ -99,22 +101,6 @@
void
set_socktype(void)
{
-#ifdef USE_SOCKETS_AS_HANDLES
-#if defined(USE_ITHREADS)
- dTHX;
- if (!w32_init_socktype) {
-#endif
- int iSockOpt = SO_SYNCHRONOUS_NONALERT;
- /*
- * Enable the use of sockets as filehandles
- */
- setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE,
- (char *)&iSockOpt, sizeof(iSockOpt));
-#if defined(USE_ITHREADS)
- w32_init_socktype = 1;
- }
-#endif
-#endif /* USE_SOCKETS_AS_HANDLES */
}
@@ -399,6 +385,65 @@
return r;
}
+#ifdef USE_SOCKETS_AS_HANDLES
+#define WIN32_OPEN_SOCKET(af, type, protocol) open_ifs_socket(af, type, protocol)
+
+void
+convert_proto_info_w2a(WSAPROTOCOL_INFOW *in, WSAPROTOCOL_INFOA *out)
+{
+ Copy(in, out, 1, WSAPROTOCOL_INFOA);
+ wcstombs(out->szProtocol, in->szProtocol, sizeof(out->szProtocol));
+}
+
+SOCKET
+open_ifs_socket(int af, int type, int protocol)
+{
+ unsigned long proto_buffers_len = 0;
+ int error_code;
+ SOCKET out = INVALID_SOCKET;
+
+ if (WSCEnumProtocols(NULL, NULL, &proto_buffers_len, &error_code) == SOCKET_ERROR
+ && error_code == WSAENOBUFS)
+ {
+ WSAPROTOCOL_INFOW *proto_buffers;
+ int protocols_available = 0;
+
+ New(1, proto_buffers, proto_buffers_len / sizeof(WSAPROTOCOL_INFOW),
+ WSAPROTOCOL_INFOW);
+
+ if ((protocols_available = WSCEnumProtocols(NULL, proto_buffers,
+ &proto_buffers_len, &error_code)) != SOCKET_ERROR)
+ {
+ int i;
+ for (i = 0; i < protocols_available; i++)
+ {
+ WSAPROTOCOL_INFOA proto_info;
+
+ if ((af != AF_UNSPEC && af != proto_buffers[i].iAddressFamily)
+ || (type != proto_buffers[i].iSocketType)
+ || (protocol != 0 && protocol != proto_buffers[i].iProtocol))
+ continue;
+
+ if ((proto_buffers[i].dwServiceFlags1 & XP1_IFS_HANDLES) == 0)
+ continue;
+
+ convert_proto_info_w2a(&(proto_buffers[i]), &proto_info);
+
+ out = WSASocket(af, type, protocol, &proto_info, 0, 0);
+ break;
+ }
+ }
+
+ Safefree(proto_buffers);
+ }
+
+ return out;
+}
+
+#else
+#define WIN32_OPEN_SOCKET(af, type, protocol) socket(af, type, protocol)
+#endif
+
SOCKET
win32_socket(int af, int type, int protocol)
{
@@ -408,7 +453,8 @@
SOCKET_TEST(s = socket(af, type, protocol), INVALID_SOCKET);
#else
StartSockets();
- if((s = socket(af, type, protocol)) == INVALID_SOCKET)
+
+ if((s = WIN32_OPEN_SOCKET(af, type, protocol)) == INVALID_SOCKET)
errno = WSAGetLastError();
else
s = OPEN_SOCKET(s);
End of Patch.