Front page | perl.perl5.porters |
Postings from March 2016
Re: Putting Winsock errors into $^E
March 16, 2016 17:23
Re: Putting Winsock errors into $^E
Message ID: CAO9t-vWHO7gt2UPhLAE_==sz5Z=+CimfSE6Kx8AKwUXKswmXemail@example.com
I'd like to present a little bit different perspective of the situation
than presented here.
On Wed, Feb 17, 2016 at 3:59 AM, Steve Hay via perl5-porters <
> Nearly a year ago there was some discussion about the way in which
> perl handles errors from socket functions on Windows:
> There were two main issues:
> One was some minor breakage caused by checking for a hard-coded
> Winsock error code (10035) instead of a POSIX error constant
> (EWOULDBLOCK) which they are mapped to.
The values placed in $!
> changed in 5.20.0 to incorporate the same mapping of WSAE* values to
> E* that had long been in effect since 5.8 in Errno.pm and 5.12 in
> POSIX.pm. This was done to avert some problems caused by the addition
> of new POSIX error constants in the errno.h of VC10+ and recent gccs.
> The danger of breakage for anyone using hard-coded error codes was
> documented in 5.20.0's perldelta:
That's a twisted way to present things.
Checking for Winsock error codes was legitimate (as long as Perl had been
returning WSA* codes for socket calls).
The fact that hardcoded values where used instead of Perl's E* codes made
also prefect sense when considering portability and/or the inadequation of
the E* code semantics on Windows.
The cause of the breakage is that p5p decided to affect POSIX codes to $!
instead of the WSA one for winsock calls.
> The second, more significant, issue is the fact that this old mapping,
> despite many other languages apparently having similar code in them
> (e.g. similar code was found in each of Python, Ruby, Tcl and PHP), is
> not good because some similarly-named constants do not have compatible
> meanings (e.g. EINPROGRESS indicates that a non-blocking connection
> could not be immediately established and will instead be established
> asynchronously, whereas WSAEINPROGRESS indicates that a blocking
> operation (which Winsock only allows a single one of per-task or
> thread) is currently executing. In fact, WSAEWOULDBLOCK matches
> EINPROGRESS far better than WSAEINPROGRESS does).
Other languages were broken, many other libs and programs are/were
certainly equally broken. I don't think there is a point to be made here.
But it is interesting to note that some Perl libs were not, were correctly
dealing with the situation, and got broken due to the breakage above.
In the meantime, broken code stayed broken (using E* constants instead of
The issue is the namespace clash between Perl (when E* = WSAE*) and M$ (who
decides to defined related E* in a different way), especially in XS modules.
I believe (just a guess), that resolving the namespace conflict in CPAN and
XS modules (eg, by replacing E* with appropriate WSAE* constants for
winsock related errors) is considered a too huge job.
> The most robust solution that was put forward (myself, Leon and Sinan
> all suggested it) to solve the various issues with defining/exporting
> error constants and mapping/setting error codes in $! was to simply
> forget about $! and POSIX error codes for Winsock functions, and
> instead just set the Winsock error code directly into $^E.
That's an opinion. I believe this solution is rather motivated by looking
for the least work it would involve, and more precisely by trying to avoid
having to fix broken code using POSIX codes instead of WSA* ones.
> I therefore propose to leave the whole $! thing as it is now, put the
> Winsock error codes into $^E after each Winsock function call, export
> the WSAE* error constants from Errno.pm and POSIX.pm for checking
> those error codes against and henceforth encourage people to test $^E
> (against WSAE* constants) rather than $! (against E* constants) on
> Windows from 5.24.0 onwards.
I still consider this a not so good solution because:
- it still breaks compatibility with correct code and older perls
- $! continues to hold E* posix codes that are misleading for winsock
- CPAN/XS/... code using E* instead of WSAE* one is still broken. And
nothing prevents new code to fall in this trap again.
Basically, making correct portable code, between platforms and perl
versions, gets harder than ever for sockets.
What I would consider "correct" would be:
- let E* codes be POSIX (we agree on that), to solve the namespace clash.
- let $! return the correct codes (WSA*) for winsock calls, at least when
E* POSIX semantic is not 100% compatible.
- that does not break compatibility with "correct" code (not using POSIX
error codes with a non-POSIX semantic).
- that prevents comparison with POSIX codes to inadvertently get true (so
non-Windows code paths are not triggered inadvertently on Windows).
This is also backward compatible with older Perl versions, once broken code
get fixed regarding the namespace clash (using WSAE* codes where
appropriate instead of POSIX ones).
Obviously, the downside of this approach is that broken code (that happened
to work in most cases) gets really broken (and will certainly not work in
most cases anymore). Looking at this in a more positive way, I would say
that the broken code would not be hidden anymore, which would force it to
be fixed once and for all.
Another potential issue is that there can be at some point a clash between
WSA IDs and POSIX ones.
On a side note, I hope POSIX.pm will not export WSA* codes which are,
well... not POSIX.
> I have made the necessary code changes in the top three commits on this
> This works for me, and has smoked as cleanly as seems to be normal:
> I would like to commit this before the "user-visible changes freeze"
> on 20th, and will do so if no objections are raised. I will, of
> course, add some appropriate documentation (in perldelta and
> elsewhere) too.
As a summary, what most disturbs me on the chosen solution it that $! still
holds POSIX values that are not semantically compatible with winsock errors.
I believe that as long as you think that broken code (Perl or XS) checking
$! against E* for winsock should not be impacted by your fix, this
discussion will not progress.