AnyEvent and Strawberry perl issue
Steve Hay
steve.m.hay at googlemail.com
Sat Mar 14 15:49:34 CET 2015
On 13 March 2015 at 07:33, Marc Lehmann <schmorp at schmorp.de> wrote:
> On Wed, Mar 11, 2015 at 05:35:17PM -0400, Laurent <laurent.aml at gmail.com> wrote:
>> Apparently, in my setup of Strawberry Perl 5.20, syswrite reports
>> POSIX::EWOULDBLOCK (140) instead of the WSAEWOULDBLOCK (10035) or EAGAIN.
>> In particular, this makes the readline test fail:
>
> The pain. It never ends.
>
> Anyway, thanks for bringing this to my attention, I had no idea.
>
> This is yet another idiotic bug in perl - the corresponding error code for
> WSAEWOULDBLOCK would be EAGAIN (35), the winsock error codes are generally
> shifted by 10000. This change breaks not only existing perl programs
> (which makes it idiotic), but also most unix programs (which use EAGAIN,
> as EWOULDBLOCK is virtually unused on unix for this).
>
> (mingw gets it right, e.g.
> http://lists.gnu.org/archive/html/bug-gnulib/2008-10/msg00068.html, so
> again, I would have to recommend cygwin perl as this doesn't rely on the
> broken unix emulation code in perl, and of course also gets this right).
>
> I call it a bug because needlessly breaking compatibility with both
> existing unix and windows code is just that - idiotic, and the only place
> to fix it would be in strawberry perl (or perl). It's basically a change
> *designed* to break compatibility with everything. And of course yet
> another mindless change not tested or researched in any way.
>
> However, since the perl5porters officially give a fuck about backwards
> compatibility with existing code, chances of this getting fixed are small,
> so I will have to slow down AnyEvent by checking for EWOULDBLOCK for just
> this platform - that's what you get for letting perl6 people take over
> perl5 to destroy that, too.
As I noted previously in
http://www.nntp.perl.org/group/perl.perl5.porters/2015/03/msg226589.html
this level of backwards-compatibility breakage was an unavoidable
consequence of fixing something else. The breakage only occurs if
you're testing for hard-coded numbers like 10035 rather than named
constants like EWOULDBLOCK, and it was on that basis that it was
deemed acceptable.
I was not aware that some would argue for WSAEWOULDBLOCK to be mapped
to EAGAIN instead of EWOULDBLOCK, and I'm not entirely convinced of it
now: The patch that you cited in mingw
(http://lists.gnu.org/archive/html/bug-gnulib/2008-10/msg00068.html)
proposes doing exactly that in winsock.c:
+ case WSAEWOULDBLOCK:
+ errno = EAGAIN;
+ break;
but one reply to that message
(http://lists.gnu.org/archive/html/bug-gnulib/2008-10/msg00072.html)
says "Why should this be done? POSIX [1] does not require this.
Portable applications have to check against both EAGAIN and
EWOULDBLOCK." and cited the page
http://pubs.opengroup.org/onlinepubs/009695399/basedefs/errno.h.html
which only notes that EAGAIN and EWOULDBLOCK *may* be the same value.
There is no *requirement* for them to be the same value, hence the
statement that portable applications must check both EAGAIN and
EWOULDBLOCK. If you had done so (i.e. tested against EAGAIN and
EWOULDBLOCK, instead of testing against EAGAIN and 10035) then no
breakage would have occurred.
Furthermore, subsequent replies to the mingw email that you cited make
it clear that the above patch was not applied anyway. The final patch
in http://lists.gnu.org/archive/html/bug-gnulib/2008-10/msg00076.html
still maps WSAEWOULDBLOCK to EWOULDBLOCK in winsock.c, and only
achieves the result of that being the same value as EAGAIN by this
change in errno.h:
+/* POSIX says that EAGAIN and EWOULDBLOCK may have the same value. */
+# define EWOULDBLOCK EAGAIN
but I do not think it is perl's place to go making changes like that
to the compiler suite's errno.h. Perl should simply use whatever
errno.h is supplied. (Indeed, it was an earlier perl patch
(912c63ed00) that *had* altered the value of some Exxx constants that
caused the very breakage which the series of patches in question
(b0ba219002 to 7bf1409065) resolved. The problem was that if perl
changes some Exxx values in errno.h then those values no longer match
the values used by other libraries built with the standard errno.h,
causing conflicts in XS modules that link against other libraries in
addition to perl. So I really don't want to go down that road again.)
I do not know which version of mingw those messages are talking about
but they don't seem to bear any relation to current MinGW-w64
compilers (which are what is used by both ActivePerl and Strawberry
Perl, by far the two most prevalent perl builds on Windows); nor VC++
compilers either: Consider the following C program:
#include <errno.h>
#include <stdio.h>
int main(void) {
printf("EWOULDBLOCK=%d\n", EWOULDBLOCK);
printf("EAGAIN=%d\n", EAGAIN);
return 0;
}
When I build this with MinGW-w64's gcc-4.8.0 it outputs:
EWOULDBLOCK=140
EAGAIN=11
so they are not the same value anyway. (And EAGAIN isn't 35 either,
btw.) Visual C++ 2010 produces the same output.
So I still think the correct answer here is for AnyEvent to test for
both EAGAIN and EWOULDBLOCK, as any portable application should do.
>
>> Apparently, Perl 5.12 introduced the POSIX error codes for winsock (see
>> http://perldoc.perl.org/5.12.0/perldelta.html). In particular, EWOULDBLOCK
>> and EINPROGRESS are now supported on Windows.
>
> The next problem here is that WSAEINPROGRESS doesn't correspond to POSIX
> EINPROGRESS at all - they only have similar names and codes, but behaviour
> is not compatible. For example, AnyEvent::Socket relies on the correct
> error code (WSAEWOULDBLOCK instead of EINPROGRESS):
>
> (connect $state{fh}, $sockaddr)
> || ($! == Errno::EINPROGRESS # POSIX
> || $! == Errno::EWOULDBLOCK
> # WSAEINPROGRESS intentionally not checked - it means something else entirely
> || $! == AnyEvent::Util::WSAEINVAL # not convinced, but doesn't hurt
> || $! == AnyEvent::Util::WSAEWOULDBLOCK)
>
> cygwin gets this right as well.
>
> So this change probably breaks connections because the WSA error code is
> mapped on the wrong POSIX code. I don't think this can be fixed nicely
> either, it needs to be fixed in perl, where the incorrect mapping is.
I do not see how this will break. If the WSAGetLastError() code that
you're testing for is WSAEWOULDBLOCK then the existing check in the
code above for EWOULDBLOCK will correctly catch it.
In 5.19.3 WSAEWOULDBLOCK (10035) would have been assigned to $!, and
10035 was also the value of EWOULDBLOCK.
In 5.19.4 built with VC10 (and recent gcc compilers having the new
Exxx constants in errno.h like VC10 has) WSAEWOULDBLOCK (10035) will
get mapped to EWOULDBLOCK (140) before assignment to $!, and now 140
is the value of EWOULDBLOCK.
(And in 5.19.4 built with VC9 (and older gcc compilers) the results
are the same as 5.19.3.)
So in all cases the test against EWOULDBLOCK works and there is no
breakage. (And the test against your own
AnyEvent::Util::WSAEWOULDBLOCK, which is basically just a hard-coded
10035, is redundant.)
>
> So, summarily, the only fix is to make perl report the correct error
> codes, and not substitute similarly-sounding-but-different-behaviour ones
> from POSIX.
I am not yet convinced of any problem with our mapping of WSAExxx
codes to Exxx codes when these are assigned to $!, but I would be
interested to hear of any other concrete examples of problems that you
have encountered which do not boil down to having tested hard-coded
numbers instead of using named constants.
If there are indeed other problems in the current design then we
would, of course, be keen to fix them, although doing so in a manner
that doesn't reintroduce other bugs that have already been fixed may
not be easy.
More information about the anyevent
mailing list