From: Steve Hay Date: Fri, 6 Aug 2004 12:55:31 +0000 (+0000) Subject: Fix [perl #24269] socket() call uses non-IFS providers X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=036c1c1eb70a0dfc5a7187959eb5e39d499c9396;p=p5sagit%2Fp5-mst-13.2.git Fix [perl #24269] socket() call uses non-IFS providers causing subsequent print/read to hang or misbehave Patch supplied by Artiom Morozov in the bug report at http://rt.perl.org/rt3/index.html?q=24269 p4raw-id: //depot/perl@23200 --- diff --git a/README.win32 b/README.win32 index 3688a32..9d99244 100644 --- a/README.win32 +++ b/README.win32 @@ -739,6 +739,12 @@ in the Win32 environment. See L. Most C related calls are supported, but they may not behave as on Unix platforms. See L 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 diff --git a/win32/Makefile b/win32/Makefile index 3039a0d..ccdbca0 100644 --- a/win32/Makefile +++ b/win32/Makefile @@ -303,7 +303,7 @@ ARCHNAME = $(ARCHNAME)-thread # 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 @@ BUILDOPT = $(BUILDOPT) -DPERL_MSVCRT_READFIX 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 diff --git a/win32/makefile.mk b/win32/makefile.mk index c43a881..bcb5e98 100644 --- a/win32/makefile.mk +++ b/win32/makefile.mk @@ -290,7 +290,7 @@ ARCHNAME !:= $(ARCHNAME)-thread # 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 @@ LIBC = -lmsvcrt 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 @@ BUILDOPT += -DPERL_MSVCRT_READFIX 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 diff --git a/win32/win32.c b/win32/win32.c index 2e5db2c..0db36b3 100644 --- a/win32/win32.c +++ b/win32/win32.c @@ -5113,7 +5113,6 @@ Perl_sys_intern_init(pTHX) 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 @@ Perl_sys_intern_dup(pTHX_ struct interp_intern *src, struct interp_intern *dst) 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); diff --git a/win32/win32.h b/win32/win32.h index 778dd21..4c5dee6 100644 --- a/win32/win32.h +++ b/win32/win32.h @@ -358,9 +358,6 @@ struct thread_intern { 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 @@ DllExport int win32_async_check(pTHX); #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) diff --git a/win32/win32sck.c b/win32/win32sck.c index 86cdc5f..0e2be30 100644 --- a/win32/win32sck.c +++ b/win32/win32sck.c @@ -16,6 +16,8 @@ #define Win32_Winsock #endif #include +#include + #include "EXTERN.h" #include "perl.h" @@ -86,11 +88,11 @@ start_sockets(void) * 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 @@ start_sockets(void) 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 @@ win32_closesocket(SOCKET s) 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 @@ win32_socket(int af, int type, int protocol) 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);