develooper Front page | perl.perl5.porters | Postings from March 2016

Re: Putting Winsock errors into $^E

Thread Previous | Thread Next
March 16, 2016 22:56
Re: Putting Winsock errors into $^E
Message ID:

On Wed, Mar 16, 2016 at 2:37 PM, Steve Hay <>

> On 16 March 2016 at 17:23, Laurent <> wrote:


> >
> > 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.
> >
> I do indeed believe that code checking $! against E* for Winsock
> should not be impacted. The change that was made in 5.20 was careful
> to update the values put into $! *and* the values of the E* constants
> exported from Errno and POSIX so that they remained in sync because we
> believed that most people checked $! against E*, and it remains the
> case that I would not want to impact that.
> It's clear now that in some cases people quite legitimately don't do
> that (due to the non-equivalence of like-named E* and WSAE*
> constants), but it's still surely true that there is a lot of code
> that does test $! against E* and is working fine since many like-named
> E* and WSAE* constants are equivalent. I think it's wrong to say that
> all such code is "broken", just as we were wrong when making changes
> in 5.20 to believe that code checking $! against hard-coded numbers
> was "broken" and should simply be "fixed" to use E* constants instead.

There we disagree.
Using a POSIX constant that has a defined semantic, for something else that
has a different semantic (the WSA one), is broken by design (even more in a
cross-platform language).
This is not an opinion, this is a fact. That's part of my definition of
broken, if you wish.
I disagree with your argument that because the code "works" (to some
extend) then it is not broken. Perl, for instance, has been broken for this
reason for years (assigning WSA* codes to E* constants), but "worked
fine"... until the namespace clash happened. And your solution is still
broken as it puts a WSA error into $! with a POSIX code.

There are also example of code "working fine", eg: assuming that keys of
hashes were always sorted in the same order, that got "fixed" anyway (no
intent to debate more on this).

It may happen that the semantic differences does not have a visible effect
in 95% of the cases; that is not enough to say that the code is not broken.
It is quite difficult to be sure that a code using POSIX constants for
winsocks is not broken. So the "safe" approach is to consider it is.

For constants where you are 100% sure they are semantically compatible
(*WOULDBLOCK?), that could help backward compatibility (let broken code
still "work"), though with adding some confusion around which E constants
can or cannot be used.

> So I believe that any change that causes code testing $! against E* to
> break would be bad, in exactly the same way as the change in 5.20
> breaking comparisons of $! against hard-coded numbers turned out to be
> bad. In fact, I think it would cause even more backwards-compatibility
> breakage because probably more code would be affected.

You are comparing breaking potentially broken code with breaking probably
non-broken code. That's not the same thing.
The issue is that it seems there is much more potentially broken code than
probably non-broken one.

> This is why I believe that the safest solution, avoiding any more
> backwards-compatibility breakage in existing code, is to start afresh,
> with the unadulterated Winsock error value placed in a new location
> ($^E) and a set of WSAE* constants made available for testing against.

My vision is that the objective is the least possible work, not safety, nor
robustness, both which are contradictory with allowing semantic twist.
That's a sensible objective, I just wish it would not be the main one.

> We now have POSIX values that match E* constants placed in $! (albeit
> with a warning that I have promised to add to the documentation in
> relevant places that the mapping of Winsock values to those POSIX
> values is wrong in some cases), and Winsock values that match WSAE*

When is it not wrong? That's certainly quite hard to tell... so hard that
one should rather assume this will not completely work as expected.

> constants placed in $^E. I think that is quite a sensible state of
> affairs, given that $! is normally a representation of the
> (cross-platform) C "errno" variable and $^E is an OS-specific error
> variable.

> (I've written before that I think part of the confusion in where to
> put Winsock error codes arises because Winsock functions like
> accept(), connect() and select() correspond to functions available on
> other OSes, and so, since they are not OS-specific, you might expect
> E*-based error codes in $! (exactly as you have for CRT functions,
> even on Windows), and yet (unlike MS CRT functions) these Winsock
> functions do not actually set the C "errno" variable which $! is
> intended to correspond to...)

The issue is that you place in $! a POSIX value which is not semantically
compatible with the winsock error.
Any other option but this one would look more sensible to me, eg: returning
no error (ie, check $^E), or an error telling you that an OS-level error
occurred (ie: check $^E), or the WSA code.
But requesting $!/E* comparison to still work prevents any of those.

There is indeed a lot of confusion around winsock. But making it look like
unix sockets with POSIX error codes certainly does not help solve this

> Code that continues to test $! against E* will continue to work
> exactly as it always has done. In some cases, such tests never did
> work and people had to test $! against hard-coded numbers instead. We
> broke that in 5.20, not realizing that such uses of hard-coded numbers
> was necessary. I'm sorry about that but I don't think that another
> round of backwards-compatibility-breaking changes here would be a good
> thing or would make things any better.
> So instead, I'm proposing that in future people should switch code
> testing $! against E* over to testing $^E against WSAE* on Windows. I
> don't believe that is any harder for people to do than switching over
> to testing $! against hard-coded numbers (or exported WSAE* constants)
> on Windows, which is what you're proposing, if I have understood
> correctly.

I don't believe it either, but that's of no importance.

I believe that people will continue to confuse WSAE* and E*:
- as Perl let them do this (as Perl actually does it itself in $!)
- as Perl doc often does not define error codes, leaving users check the
system man pages instead (and by habit... one could directly go to man
pages in such cases).
- because when porting Perl code to Windows, one can easily overlook the
problem as the broken $! comparison will possibly hide the issue.
- as there will be many examples of broken code in the wild (including in
CPAN, given that modules have no strong reasons to fix their code).

-- Laurent

Thread Previous | Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About