This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Fix a problem with mod_perl on Windows using VS2010+.
authorSteve Hay <steve.m.hay@googlemail.com>
Tue, 3 Sep 2013 21:57:29 +0000 (22:57 +0100)
committerSteve Hay <steve.m.hay@googlemail.com>
Mon, 16 Sep 2013 14:37:30 +0000 (15:37 +0100)
commitb0ba21900202318f75a549d9ac72765fc83945c6
treee97bb686f7b6855400e2a91b75471c2755be7c1c
parenta05353bfa2b031e0c0283559432496d3915c83b2
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.
MANIFEST
ext/Errno/Errno_pm.PL
ext/POSIX/POSIX.xs
ext/POSIX/lib/POSIX.pm
win32/include/sys/errno2.h [new file with mode: 0644]
win32/include/sys/socket.h
win32/win32.c
win32/win32sck.c