From: Jan Dubois Date: Fri, 13 Nov 2009 19:45:46 +0000 (-0800) Subject: Support $! stringification of socket error codes on Windows. X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=364d54baf6add9c4667b89e1656f226d0882a843;p=p5sagit%2Fp5-mst-13.2.git Support $! stringification of socket error codes on Windows. The winsock error codes from WSAGetLastError() are stored by Perl in errno, and there is some code in win32_strerror() that would stringify them, but that code is never called when Perl is built with the default WIN32IO_IS_STDIO setting. This patch enables the win32_strerror() override unconditionally and also fixes a potential memory corruption issue by using the FORMAT_MESSAGE_IGNORE_INSERTS flag to ignore any parameter substitution codes that may be embedded in the error message. This now works as expected: C:\git\perl>perl -Ilib -MPOSIX -E "$!=POSIX::EWOULDBLOCK; say $!" A non-blocking socket operation could not be completed immediately. --- diff --git a/win32/win32.c b/win32/win32.c index 0302836..050c50c 100644 --- a/win32/win32.c +++ b/win32/win32.c @@ -64,7 +64,6 @@ typedef struct { #define PERL_NO_GET_CONTEXT #include "XSUB.h" -#include "Win32iop.h" #include #ifndef __GNUC__ /* assert.h conflicts with #define of assert in perl.h */ @@ -2623,21 +2622,24 @@ win32_strerror(int e) #if !defined __BORLANDC__ && !defined __MINGW32__ /* compiler intolerance */ extern int sys_nerr; #endif - DWORD source = 0; if (e < 0 || e > sys_nerr) { dTHX; if (e < 0) e = GetLastError(); - if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, &source, e, 0, - w32_strerror_buffer, - sizeof(w32_strerror_buffer), NULL) == 0) + if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM + |FORMAT_MESSAGE_IGNORE_INSERTS, NULL, e, 0, + w32_strerror_buffer, sizeof(w32_strerror_buffer), + NULL) == 0) + { strcpy(w32_strerror_buffer, "Unknown Error"); - + } return w32_strerror_buffer; } +#undef strerror return strerror(e); +#define strerror win32_strerror } DllExport void diff --git a/win32/win32iop.h b/win32/win32iop.h index b03e9a7..7507408 100644 --- a/win32/win32iop.h +++ b/win32/win32iop.h @@ -161,7 +161,9 @@ DllExport Sighandler_t win32_signal(int sig, Sighandler_t subcode); END_EXTERN_C #undef alarm -#define alarm win32_alarm +#define alarm win32_alarm +#undef strerror +#define strerror win32_strerror /* * the following six(6) is #define in stdio.h @@ -205,7 +207,6 @@ END_EXTERN_C #define ferror(f) win32_ferror(f) #define errno (*win32_errno()) #define environ (*win32_environ()) -#define strerror win32_strerror /* * redirect to our own version @@ -294,6 +295,10 @@ END_EXTERN_C #define free win32_free #endif +/* XXX Why are APIs like sleep(), times() etc. inside a block + * XXX guarded by "#ifndef WIN32IO_IS_STDIO"? + */ + #define pipe(fd) win32_pipe((fd), 512, O_BINARY) #define pause() win32_sleep((32767L << 16) + 32767) #define sleep win32_sleep