summaryrefslogtreecommitdiff
path: root/win32/include
diff options
context:
space:
mode:
authorSteve Hay <steve.m.hay@googlemail.com>2013-09-03 22:57:29 +0100
committerSteve Hay <steve.m.hay@googlemail.com>2013-09-16 15:37:30 +0100
commitb0ba21900202318f75a549d9ac72765fc83945c6 (patch)
treee97bb686f7b6855400e2a91b75471c2755be7c1c /win32/include
parenta05353bfa2b031e0c0283559432496d3915c83b2 (diff)
downloadperl-b0ba21900202318f75a549d9ac72765fc83945c6.tar.gz
Fix a problem with mod_perl on Windows using VS2010+.
The problem is caused by the following two commits, which sought to deal with new Exxx values (with values >= 100) in errno.h which Microsoft added in VS2010: http://perl5.git.perl.org/perl.git/commit/b59e75b34cef3fedd214c9b6ee744146cf8b3308 http://perl5.git.perl.org/perl.git/commit/912c63ed00375338703043928cac3c740d00cc9d The former commit was mostly a patch to Errno and POSIX, together with some other cleaning up in win32/win32.h and win32/include/sys/socket.h; the latter commit was a fixup to win32/include/sys/socket.h which restored (more aggressively) the ENOTSOCK->WSAENOTSOCK redefinition and added similar redefinitions for ECONNABORTED, ECONNRESET and EAFNOSUPPORT. It is the latter commit which causes this little program to output ECONNABORTED=10053 rather than ECONNABORTED=106 as it ought to do in VC10 (and higher) builds of perl: #include <windows.h> #include "EXTERN.h" #include "perl.h" #include "XSUB.h" void main(void) { printf("ECONNABORTED=%d\n", ECONNABORTED); } That change is now causing problems with mod_perl, in which the (Perl level) APR::Status::is_ECONNABORTED() and the (C level) APR_STATUS_IS_ECONNABORTED() which it calls are failing to recognize an aborted connection (indicated by error code ECONNABORTED set by Apache httpd.exe). The APR_STATUS_IS_ECONNABORTED() macro is picked up by mod_perl from APR's apr_errno.h: #define APR_STATUS_IS_ECONNABORTED(s) ((s) == APR_ECONNABORTED \ || (s) == APR_OS_START_SYSERR + WSAECONNABORTED) where #ifdef ECONNABORTED #define APR_ECONNABORTED ECONNABORTED #else #define APR_ECONNABORTED (APR_OS_START_CANONERR + 18) #endif When this is compiled into httpd.exe ECONNABORTED is 106 (from errno.h) and APR_STATUS_IS_ECONNABORTED(s) amounts to #define APR_STATUS_IS_ECONNABORTED(s) ((s) == 106 || (s) == 730053) but when compiled into APR/Status.dll ECONNABORTED is 10053 (redefined to WSAECONNABORTED as above) so APR_STATUS_IS_ECONNABORTED(s) then amounts to #define APR_STATUS_IS_ECONNABORTED(s) ((s) == 10053 || (s) == 730053) which doesn't pick up an error code of 106 coming from httpd.exe. This could be worked around in mod_perl by redefining ECONNABORTED and the other three back to their original errno.h values to match what httpd.exe is using, but that might just cause problems in the other direction, with those values no longer matching the values which perl.exe is using. Moreoever, this problem could affect other XS interfaces (not just mod_perl), so it really needs to be fixed in perl. This commit implements the alternative solution mentioned the commit message for the first commit cited above. (As noted in that previous commit message, this solution equally has potential problems, missing out on the advantages of the original solution implemented, namely, better backwards compatibility with other perl code having hard-coded numeric error codes, but this will be unavoidable if we want to get to a sane state.) Note that changing the $! values is an incompatible change, so should probably not be done for 5.18.x. That's unfortunate for mod_perl (and anything else similarly affected), but that will just have to either live with the breakage (which was introduced in 5.14.0) until 5.20.0 or else try the workaround mentioned above for 5.14.x, 5.16.x and 5.18.x. The main change is to use a new function throughout win32/win32sck.c to convert WSAGetLastError() values into errno.h constants before assigning to errno. Every possible WSAExxx value (as documented by MSDN) is mapped to an Exxx value, although it is still possible for other WSAxxx values to get assigned to errno unchanged (but that has always been the case, and any non-existent Exxx values get mapped back to WSAExxx values anyway...). We must then ensure that all of those Exxx values are defined, which is now done (in the new file, win32/include/sys/errno2.h) in a friendlier manner, being careful not to redefine any (specifically the new ones in VC++ 2010 and above) which already exist. The rest are defined as the WSAExxx values, as mentioned above. Finally, we need the Errno module to know about these values, which is done by having it include that same new header file to ensure that it gets the same definitions, rather than having to play its own games. The new header is also used in POSIX, which similarly wants definitions of as many as possible of its hard-coded list of Exxx values.
Diffstat (limited to 'win32/include')
-rw-r--r--win32/include/sys/errno2.h169
-rw-r--r--win32/include/sys/socket.h14
2 files changed, 170 insertions, 13 deletions
diff --git a/win32/include/sys/errno2.h b/win32/include/sys/errno2.h
new file mode 100644
index 0000000000..076ed01b30
--- /dev/null
+++ b/win32/include/sys/errno2.h
@@ -0,0 +1,169 @@
+#ifndef _INC_SYS_ERRNO2
+#define _INC_SYS_ERRNO2
+
+#define _WINSOCKAPI_ /* Don't drag in everything */
+#include <winsock.h>
+
+/* Ensure all the Exxx constants required by get_last_socket_error() in
+ * win32/win32sck.c are defined. Many are defined in <errno.h> already (more in
+ * VC++ 2010 and above) so, for the sake of compatibility with third-party code
+ * linked into XS modules, we must be careful not to redefine them; for the
+ * remainder we define our own values, namely the corresponding WSAExxx values.
+ * These definitions are also used as a supplement to the use of <errno.h> in
+ * the Errno and POSIX modules, both of which may be used to test the value of
+ * $!, which may have these values assigned to it (via win32/win32sck.c). It
+ * also provides numerous otherwise missing values in the (hard-coded) list of
+ * Exxx constants exported by POSIX.
+ */
+#ifndef EINTR
+# define EINTR WSAEINTR
+#endif
+#ifndef EBADF
+# define EBADF WSAEBADF
+#endif
+#ifndef EACCES
+# define EACCES WSAEACCES
+#endif
+#ifndef EFAULT
+# define EFAULT WSAEFAULT
+#endif
+#ifndef EINVAL
+# define EINVAL WSAEINVAL
+#endif
+#ifndef EMFILE
+# define EMFILE WSAEMFILE
+#endif
+#ifndef EWOULDBLOCK
+# define EWOULDBLOCK WSAEWOULDBLOCK
+#endif
+#ifndef EINPROGRESS
+# define EINPROGRESS WSAEINPROGRESS
+#endif
+#ifndef EALREADY
+# define EALREADY WSAEALREADY
+#endif
+#ifndef ENOTSOCK
+# define ENOTSOCK WSAENOTSOCK
+#endif
+#ifndef EDESTADDRREQ
+# define EDESTADDRREQ WSAEDESTADDRREQ
+#endif
+#ifndef EMSGSIZE
+# define EMSGSIZE WSAEMSGSIZE
+#endif
+#ifndef EPROTOTYPE
+# define EPROTOTYPE WSAEPROTOTYPE
+#endif
+#ifndef ENOPROTOOPT
+# define ENOPROTOOPT WSAENOPROTOOPT
+#endif
+#ifndef EPROTONOSUPPORT
+# define EPROTONOSUPPORT WSAEPROTONOSUPPORT
+#endif
+#ifndef ESOCKTNOSUPPORT
+# define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
+#endif
+#ifndef EOPNOTSUPP
+# define EOPNOTSUPP WSAEOPNOTSUPP
+#endif
+#ifndef EPFNOSUPPORT
+# define EPFNOSUPPORT WSAEPFNOSUPPORT
+#endif
+#ifndef EAFNOSUPPORT
+# define EAFNOSUPPORT WSAEAFNOSUPPORT
+#endif
+#ifndef EADDRINUSE
+# define EADDRINUSE WSAEADDRINUSE
+#endif
+#ifndef EADDRNOTAVAIL
+# define EADDRNOTAVAIL WSAEADDRNOTAVAIL
+#endif
+#ifndef ENETDOWN
+# define ENETDOWN WSAENETDOWN
+#endif
+#ifndef ENETUNREACH
+# define ENETUNREACH WSAENETUNREACH
+#endif
+#ifndef ENETRESET
+# define ENETRESET WSAENETRESET
+#endif
+#ifndef ECONNABORTED
+# define ECONNABORTED WSAECONNABORTED
+#endif
+#ifndef ECONNRESET
+# define ECONNRESET WSAECONNRESET
+#endif
+#ifndef ENOBUFS
+# define ENOBUFS WSAENOBUFS
+#endif
+#ifndef EISCONN
+# define EISCONN WSAEISCONN
+#endif
+#ifndef ENOTCONN
+# define ENOTCONN WSAENOTCONN
+#endif
+#ifndef ESHUTDOWN
+# define ESHUTDOWN WSAESHUTDOWN
+#endif
+#ifndef ETOOMANYREFS
+# define ETOOMANYREFS WSAETOOMANYREFS
+#endif
+#ifndef ETIMEDOUT
+# define ETIMEDOUT WSAETIMEDOUT
+#endif
+#ifndef ECONNREFUSED
+# define ECONNREFUSED WSAECONNREFUSED
+#endif
+#ifndef ELOOP
+# define ELOOP WSAELOOP
+#endif
+#ifndef ENAMETOOLONG
+# define ENAMETOOLONG WSAENAMETOOLONG
+#endif
+#ifndef EHOSTDOWN
+# define EHOSTDOWN WSAEHOSTDOWN
+#endif
+#ifndef EHOSTUNREACH
+# define EHOSTUNREACH WSAEHOSTUNREACH
+#endif
+#ifndef ENOTEMPTY
+# define ENOTEMPTY WSAENOTEMPTY
+#endif
+#ifndef EPROCLIM
+# define EPROCLIM WSAEPROCLIM
+#endif
+#ifndef EUSERS
+# define EUSERS WSAEUSERS
+#endif
+#ifndef EDQUOT
+# define EDQUOT WSAEDQUOT
+#endif
+#ifndef ESTALE
+# define ESTALE WSAESTALE
+#endif
+#ifndef EREMOTE
+# define EREMOTE WSAEREMOTE
+#endif
+#ifndef EDISCON
+# define EDISCON WSAEDISCON
+#endif
+#ifndef ENOMORE
+# define ENOMORE WSAENOMORE
+#endif
+#ifndef ECANCELLED
+# define ECANCELLED WSAECANCELLED
+#endif
+#ifndef EINVALIDPROCTABLE
+# define EINVALIDPROCTABLE WSAEINVALIDPROCTABLE
+#endif
+#ifndef EINVALIDPROVIDER
+# define EINVALIDPROVIDER WSAEINVALIDPROVIDER
+#endif
+#ifndef EPROVIDERFAILEDINIT
+# define EPROVIDERFAILEDINIT WSAEPROVIDERFAILEDINIT
+#endif
+#ifndef EREFUSED
+# define EREFUSED WSAEREFUSED
+#endif
+
+#endif /* _INC_SYS_ERRNO2 */
diff --git a/win32/include/sys/socket.h b/win32/include/sys/socket.h
index 6009572725..d658913f8b 100644
--- a/win32/include/sys/socket.h
+++ b/win32/include/sys/socket.h
@@ -177,23 +177,11 @@
# define EAI_NODATA WSANO_DATA
#endif
-#include "win32.h"
-
#ifdef __cplusplus
extern "C" {
#endif
-#undef ENOTSOCK
-#define ENOTSOCK WSAENOTSOCK
-
-#undef ECONNABORTED
-#define ECONNABORTED WSAECONNABORTED
-
-#undef ECONNRESET
-#define ECONNRESET WSAECONNRESET
-
-#undef EAFNOSUPPORT
-#define EAFNOSUPPORT WSAEAFNOSUPPORT
+#include "errno2.h"
#ifndef PERL_FD_SETSIZE
#define PERL_FD_SETSIZE 64