Skip to content

IO::Socket fails with Bareword error #20355

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
drq883 opened this issue Sep 27, 2022 · 31 comments
Open

IO::Socket fails with Bareword error #20355

drq883 opened this issue Sep 27, 2022 · 31 comments

Comments

@drq883
Copy link

drq883 commented Sep 27, 2022

Module: IO::Socket

Description
When including the IO::Socket module using a perl5.20.2 built from source, we're seeing this output:

Bareword "Errno::EINVAL" not allowed while "strict subs" in use at /sasopt/perl/B64/osrel-13.1-RELEASE/5.20.2/lib/site_perl/5.20.2/amd64-freebsd-thread-multi/IO/Socket.pm line 141

We traced it down to the code here:

      elsif (!connect($sock,$addr) &&
                not ($!{EISCONN} || ($^O eq 'MSWin32' &&
                ($! == (($] < 5.019004) ? 10022 : Errno::EINVAL))))
            ) {

If we prefix the Errno::EINVALL with a & (as seen in other places in code), it works without error.

Steps to Reproduce
We build perl from source then, use the resulting cpan to install a myriad modules. And when all that is done, we get the error. If I just build from source and build no modules, run something like this, it works:

use IO::Socket;

print "hello\n";

However when we go thru all the gyrations to build source and modules, we get this output:

Bareword "Errno::EINVAL" not allowed while "strict subs" in use at /sasopt/perl/B64/osrel-13.1-RELEASE/5.20.2/lib/site_perl/5.20.2/amd64-freebsd-thread-multi/IO/Socket.pm line 141

Expected behavior
It should just print:

hello

Perl configuration
This is the perl -V that exhibits the error:

Summary of my perl5 (revision 5 version 20 subversion 2) configuration:

  Platform:
    osname=freebsd, osvers=13.1-release, archname=amd64-freebsd-thread-multi
    uname='freebsd bb04lgn91.unx.sas.com 13.1-release freebsd 13.1-release bbkern amd64 '
    config_args='-Dprefix=/usr/tmp/perlwork.sasdrq/B64/osrel-13.1-RELEASE/5.20.2 -de -Dusethreads -Duserelocatableinc -Dusesitecustomize'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=define, usemultiplicity=define
    use64bitint=define, use64bitall=define, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-DHAS_FPSETMASK -DHAS_FLOATINGPOINT_H -fwrapv -fpcc-struct-return -pipe -fstack-protector -I/usr/local/include',
    optimize='-O',
    cppflags='-DHAS_FPSETMASK -DHAS_FLOATINGPOINT_H -fwrapv -fpcc-struct-return -pipe -fstack-protector -I/usr/local/include -D__GNUC__'
    ccversion='', gccversion='10.3.0', gccosandvers=''
    intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
    ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='cc', ldflags ='-pthread -Wl,-E  -fstack-protector -L/usr/local/lib'
    libpth=/usr/lib /usr/local/lib /usr/local/lib /usr/lib
    libs=-lgdbm -ldl -lm -lcrypt -lutil
    perllibs=-ldl -lm -lcrypt -lutil
    libc=, so=so, useshrplib=false, libperl=libperl.a
    gnulibc_version=''
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags=' '
    cccdlflags='-DPIC -fPIC', lddlflags='-shared  -L/usr/local/lib -fstack-protector'


Characteristics of this binary (from libperl):
  Compile-time options: HAS_TIMES MULTIPLICITY PERLIO_LAYERS
                        PERL_DONT_CREATE_GVSV
                        PERL_HASH_FUNC_ONE_AT_A_TIME_HARD
                        PERL_IMPLICIT_CONTEXT PERL_MALLOC_WRAP
                        PERL_NEW_COPY_ON_WRITE PERL_PRESERVE_IVUV
                        USE_64_BIT_ALL USE_64_BIT_INT USE_ITHREADS
                        USE_LARGE_FILES USE_LOCALE USE_LOCALE_COLLATE
                        USE_LOCALE_CTYPE USE_LOCALE_NUMERIC USE_PERLIO
                        USE_PERL_ATOF USE_REENTRANT_API USE_SITECUSTOMIZE
  Built under freebsd
  Compiled at Jun 24 2022 15:44:28
  %ENV:
    PERLVER="5.20.2"
  @INC:
    /sasopt/perl/B64/osrel-13.1-RELEASE/5.20.2/lib/site_perl/5.20.2/amd64-freebsd-thread-multi
    /sasopt/perl/B64/osrel-13.1-RELEASE/5.20.2/lib/site_perl/5.20.2
    /sasopt/perl/B64/osrel-13.1-RELEASE/5.20.2/lib/5.20.2/amd64-freebsd-thread-multi
    /sasopt/perl/B64/osrel-13.1-RELEASE/5.20.2/lib/5.20.2
    /c/bb00na3a/vol/sasopt/perl/B64/osrel-13.1-RELEASE/5.20.2/lib/site_perl/5.20.2/amd64-freebsd-thread-multi
    /c/bb00na3a/vol/sasopt/perl/B64/osrel-13.1-RELEASE/5.20.2/lib/site_perl/5.20.2
    /c/bb00na3a/vol/sasopt/perl/B64/osrel-13.1-RELEASE/5.20.2/lib/5.20.2/amd64-freebsd-thread-multi
    /c/bb00na3a/vol/sasopt/perl/B64/osrel-13.1-RELEASE/5.20.2/lib/5.20.2
    .

This is the perl that works:

Summary of my perl5 (revision 5 version 20 subversion 2) configuration:

  Platform:
    osname=freebsd, osvers=13.1-release, archname=amd64-freebsd
    uname='freebsd bb03jsf03.unx.sas.com 13.1-release freebsd 13.1-release bbkern amd64 '
    config_args='-Dprefix=/usr/tmp/perlwork.sasdrq/B64/osrel-13.1-RELEASE/5.20.2 -de -Duserelocatableinc -Dusesitecustomize -Dcc=clang'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=undef, usemultiplicity=undef
    use64bitint=define, use64bitall=define, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='clang', ccflags ='-DHAS_FPSETMASK -DHAS_FLOATINGPOINT_H -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include',
    optimize='-O',
    cppflags='-DHAS_FPSETMASK -DHAS_FLOATINGPOINT_H -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
    ccversion='', gccversion='FreeBSD Clang 13.0.0 ([email protected]:llvm/llvm-project.git llvmorg-13.0.0-0-gd7b669b3a303)', gccosandvers=''
    intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
    ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='clang', ldflags ='-Wl,-E  -fstack-protector -L/usr/local/lib'
    libpth=/usr/lib /usr/local/lib /usr/lib/clang/13.0.0/lib /usr/lib
    libs=-lgdbm -ldl -lm -lcrypt -lutil -lc
    perllibs=-ldl -lm -lcrypt -lutil -lc
    libc=, so=so, useshrplib=false, libperl=libperl.a
    gnulibc_version=''
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags=' '
    cccdlflags='-DPIC -fPIC', lddlflags='-shared  -L/usr/local/lib -fstack-protector'


Characteristics of this binary (from libperl):
  Compile-time options: HAS_TIMES PERLIO_LAYERS PERL_DONT_CREATE_GVSV
                        PERL_HASH_FUNC_ONE_AT_A_TIME_HARD PERL_MALLOC_WRAP
                        PERL_NEW_COPY_ON_WRITE PERL_PRESERVE_IVUV
                        USE_64_BIT_ALL USE_64_BIT_INT USE_LARGE_FILES
                        USE_LOCALE USE_LOCALE_COLLATE USE_LOCALE_CTYPE
                        USE_LOCALE_NUMERIC USE_PERLIO USE_PERL_ATOF
                        USE_SITECUSTOMIZE
  Built under freebsd
  Compiled at Sep 27 2022 14:50:59
  %ENV:
    PERLVER="5.20.2"
  @INC:
    /usr/tmp/perlwork.sasdrq/B64/osrel-13.1-RELEASE/5.20.2/lib/site_perl/5.20.2/amd64-freebsd
    /usr/tmp/perlwork.sasdrq/B64/osrel-13.1-RELEASE/5.20.2/lib/site_perl/5.20.2
    /usr/tmp/perlwork.sasdrq/B64/osrel-13.1-RELEASE/5.20.2/lib/5.20.2/amd64-freebsd
    /usr/tmp/perlwork.sasdrq/B64/osrel-13.1-RELEASE/5.20.2/lib/5.20.2
    .
@Grinnz
Copy link
Contributor

Grinnz commented Sep 27, 2022

It looks like the code is not defensive enough for the parser on systems where EINVAL is not defined. This condition is only executed when $^O is MSWin32 so deferring the constant resolution to runtime as mentioned seems appropriate.

@Leont
Copy link
Contributor

Leont commented Sep 27, 2022

But why is EINVAL not defined? That sounds all wrong to me.

@Grinnz
Copy link
Contributor

Grinnz commented Sep 27, 2022

Is there any chance you could try with 1. the latest version of the IO::Socket module installed from CPAN (1.49), or 2. a more recent version of Perl?

@Grinnz
Copy link
Contributor

Grinnz commented Sep 27, 2022

(note that neither Perl 5.20.2 nor the IO distribution it's bundled with can be updated at this point, so a fix would require doing one of the above regardless)

@drq883
Copy link
Author

drq883 commented Sep 27, 2022

@Grinnz We build from source so we can use the same version across all the platforms we build here at work (FreeBSD, linux, solaris, Aix, hpux). I'm not interested in a newer version for this bug. It is only for 5.20.2 and the bundle IO::Socket with that source. I looked at the source for Socket.pm online and I think the latest is even 1.50. And that still has a bareword.

Whether or not the code is executed with $^O if MSWin32, it must pass the syntax check. And "strict subs" is active, so the error is seen.

@drq883
Copy link
Author

drq883 commented Sep 27, 2022

I have fixed the issue myself by updating the source. Just thought it might be helpful to update the actual source for future versions.

@Grinnz
Copy link
Contributor

Grinnz commented Sep 27, 2022

My point is that Perl 5.20.2 and its included version of IO cannot be updated. So it is important to determine whether the issue is present in the current versions of Perl and IO, otherwise updating them is of no benefit.

@drq883
Copy link
Author

drq883 commented Sep 27, 2022

@Grinnz understood. But maybe change the source code where it can be updated.

perl5.32.1 is installed on FreeBSD 13.1-RELEASE and it does not exhibit this error. And the barework is still there. It is version 1.43.

      elsif (!connect($sock,$addr) &&
                not ($!{EISCONN} || ($^O eq 'MSWin32' &&
                ($! == (($] < 5.019004) ? 10022 : Errno::EINVAL))))
            ) {

The version that is bundled with 5.20.2 is 1.45.

@jkeenan jkeenan added Closable? We might be able to close this ticket, but we need to check with the reporter and removed Needs Triage labels Sep 27, 2022
@jkeenan
Copy link
Contributor

jkeenan commented Sep 27, 2022

On FreeBSD-13, I wrote the following program:

$ uname -mrs
FreeBSD 13.0-RELEASE amd64

$ cat $P5P_DIR/gh-20355-io-socket.pl
use strict;
use warnings;
use IO::Socket;

print "hello\n";
print "IO::Socket version: ", $IO::Socket::VERSION, "\n";

I then did a git checkout at tag v5.20.2 and built a perl with arguments close to those used in the OP's "bad" build:

$ export GH20355_ARGS="-des -Dusedevel -Dusethreads -Duserelocatableinc -Dusesitecustomize" && \
   ~/bin/shell/install_custom_branch_for_testing \
   v5.20.2 \
   "$GH20355_ARGS"

I then ran my program with that perl:

$ cd $TESTINGDIR/v5.20.2
$ ./bin/perl -Ilib -v | head -2 | tail -1; ./bin/perl -Ilib -V:config_args
This is perl 5, version 20, subversion 2 (v5.20.2) built for amd64-freebsd-thread-multi
config_args='-des -Dusedevel -Dusethreads -Duserelocatableinc -Dusesitecustomize -Dprefix=/home/jkeenan/testing/v5.20.2 -Uversiononly -Dman1dir=none -Dman3dir=none';

$ ./bin/perl -Ilib $P5P_DIR/gh-20355-io-socket.pl
hello
IO::Socket version: 1.38

I got neither errors nor warnings. I then used the cpan associated with v5.20.2 to install the latest version of the IO distribution from CPAN. (Note that on CPAN the distribution's $VERSION is 1.50 while $IO::Socket::VERSION is still at 1.49.)

I then re-ran the program with the same (v5.20.2) version of perl but an upgraded IO::Socket.

$ ./bin/perl -Ilib $P5P_DIR/gh-20355-io-socket.pl
hello
IO::Socket version: 1.49

Once again, I got neither errors nor warnings. I cannot reproduce the problem reported in this ticket. I don't think there's any action for P5P to take. IMO the ticket is closable.

@hvds
Copy link
Contributor

hvds commented Sep 27, 2022

Once again, I got neither errors nor warnings. I cannot reproduce the problem reported in this ticket. I don't think there's any action for P5P to take. IMO the ticket is closable.

The earlier comments from @Grinnz and @Leont suggest that you will only be able to reproduce it on a platform where EINVAL is undefined. So the question would be under what circumstances that is possible, and - based on the answer to that - whether it's something we should take responsibility for defending against.

Another possible mitigation would be to have Errno detect the situation and define EINVAL to something else.

@drq883
Copy link
Author

drq883 commented Sep 27, 2022

I think the Errno::EINVAL bareword is a syntax error and should have a preceding & just like other references to &Errno:: in the same file. That's all.

If you're not going to do anything about this, then feel free to close it.

@Grinnz
Copy link
Contributor

Grinnz commented Sep 27, 2022

It's not a syntax error as long as EINVAL exists on the platform - which should be true on all platforms, so it's weird to have this issue as @Leont noted.

@Grinnz
Copy link
Contributor

Grinnz commented Sep 27, 2022

I'm curious if it's because of this issue, which was fixed in 5.20.3: #14491

@Grinnz
Copy link
Contributor

Grinnz commented Sep 27, 2022

Note that if you have that issue, you have bigger problems than just EINVAL not being defined, and I would highly recommend upgrading to 5.20.3 if possible (it's a compatible release as it's the maintenance branch)

@khwilliamson
Copy link
Contributor

khwilliamson commented Sep 28, 2022 via email

@drq883
Copy link
Author

drq883 commented Sep 28, 2022

I rebuilt perl 5.20.2 from source again, and installed all of the modules again and moved this data into production. It does not exhibit the problem I was seeing before.

@drq883
Copy link
Author

drq883 commented Sep 28, 2022

I found the problem. If I build perl using gcc (gcc version 10.3.0 (FreeBSD Ports Collection)) the problem with IO::Socket.pm shows up. Building with clang (FreeBSD clang version 13.0.0) does not show the problem.

@drq883
Copy link
Author

drq883 commented Sep 28, 2022

This is what I used to configure the perl that shows the failure:

/bin/sh Configure -Dprefix=/usr/tmp/perlwork.sasdrq/B64/osrel-13.1-RELEASE/5.20.2 -de -Duserelocatableinc -Dusesitecustomize -Dusethreads

And the gcc used was gcc10

@jkeenan
Copy link
Contributor

jkeenan commented Sep 28, 2022

This is what I used to configure the perl that shows the failure:

/bin/sh Configure -Dprefix=/usr/tmp/perlwork.sasdrq/B64/osrel-13.1-RELEASE/5.20.2 -de -Duserelocatableinc -Dusesitecustomize -Dusethreads

And the gcc used was gcc10

Okay, at last something I can reproduce.

[freebsd13: v5.20.2-gcc10] $ uname -mrs

FreeBSD 13.0-RELEASE amd64
[freebsd13: v5.20.2-gcc10] $ gcc10 --version | head -n1
gcc10 (FreeBSD Ports Collection) 10.3.0

[freebsd13: v5.20.2-gcc10] $ ./bin/perl -v | head -2 | tail -1
This is perl 5, version 20, subversion 2 (v5.20.2) built for amd64-freebsd-thread-multi

[freebsd13: v5.20.2-gcc10] $ ./bin/perl -Ilib -V:config_args
config_args='-des -Dusedevel -Dusethreads -Dcc=gcc10 -Duserelocatableinc -Dusesitecustomize -Dprefix=/home/jkeenan/testing/v5.20.2 -Uversiononly -Dman1dir=none -Dman3dir=none';

[freebsd13: testing] $ cd v5.20.2-gcc10/

[freebsd13: v5.20.2-gcc10] $ ./bin/perl -Ilib $P5P_DIR/gh-20355-io-socket.pl
Bareword "Errno::EINVAL" not allowed while "strict subs" in use at /usr/home/jkeenan/testing/v5.20.2/lib/perl5/5.20.2/amd64-freebsd-thread-multi/IO/Socket.pm line 135.

Would it be possible for you to test these scenarios?

  1. gcc11 instead of gcc10
  2. Using gcc10, eliminate -Duserelocatableinc -Dusesitecustomize, i.e., configure only with -Dgcc10 -Dusethreads
  3. Same as above, only without -Dusethreads

Thank you very much.
Jim Keenan

@drq883
Copy link
Author

drq883 commented Sep 28, 2022

I'll begin these tests now. First 2 and 3 before I try to install gcc11

@jkeenan
Copy link
Contributor

jkeenan commented Sep 28, 2022

Would it be possible for you to test these scenarios?

1. `gcc11` instead of `gcc10`

Building threaded perl on FreeBSD-13 at v5.20.2 using gcc11 I got same errors as with gcc10. When I then used ./bin/cpan IO::Socket to get latest version available on CPAN, I got many errors:

t/cachepropagate-tcp.t ... Bareword "Errno::EINVAL" not allowed while "strict subs" in use at /usr/home/jkeenan/.cpan/build/IO-1.50-O0SASN/blib/lib/IO/Socket.pm line 141.
Compilation failed in require at t/cachepropagate-tcp.t line 6.
BEGIN failed--compilation aborted at t/cachepropagate-tcp.t line 6.
t/cachepropagate-tcp.t ... Dubious, test returned 255 (wstat 65280, 0xff00)
No subtests run 
t/cachepropagate-udp.t ... Bareword "Errno::EINVAL" not allowed while "strict subs" in use at /usr/home/jkeenan/.cpan/build/IO-1.50-O0SASN/blib/lib/IO/Socket.pm line 141.
Compilation failed in require at t/cachepropagate-udp.t line 6.
BEGIN failed--compilation aborted at t/cachepropagate-udp.t line 6.
t/cachepropagate-udp.t ... Dubious, test returned 255 (wstat 65280, 0xff00)
No subtests run 
... # and so forth

@drq883
Copy link
Author

drq883 commented Sep 28, 2022

2. Using gcc10, eliminate -Duserelocatableinc -Dusesitecustomize, i.e., configure only with -Dgcc10 -Dusethreads

Same error:

% /usr/tmp/perlwork.sasdrq/B64/osrel-13.1-RELEASE/5.20.2/bin/perl
use IO::Socket;
Bareword "Errno::EINVAL" not allowed while "strict subs" in use at /usr/tmp/perlwork.sasdrq/B64/osrel-13.1-RELEASE/5.20.2/lib/5.20.2/amd64-freebsd-thread-multi/IO/Socket.pm line 135.
Compilation failed in require at - line 1.
BEGIN failed--compilation aborted at - line 1.

@drq883
Copy link
Author

drq883 commented Sep 28, 2022

3. Same as above, only without -Dusethreads

Same error as 2.

@jkeenan
Copy link
Contributor

jkeenan commented Sep 28, 2022

3. Same as above, only without -Dusethreads

Same error as 2.

And I got same failures with unthreaded build using gcc11.

[freebsd13: v5.20.2-gcc11-v5.20.2-unthreaded] $ ./bin/perl -Ilib $P5P_DIR/gh-20355-io-socket.pl
Bareword "Errno::EINVAL" not allowed while "strict subs" in use at /home/jkeenan/testing/v5.20.2/lib/perl5/5.20.2/amd64-freebsd/IO/Socket.pm line 135.
Compilation failed in require at /home/jkeenan/learn/perl/p5p/gh-20355-io-socket.pl line 3.
BEGIN failed--compilation aborted at /home/jkeenan/learn/perl/p5p/gh-20355-io-socket.pl line 3.

So it appears that when on FreeBSD-13, using gcc version 10 or 11, we build a perl, threaded or unthreaded, we encounter a build-time failure when running our test program.

Out of time today, but next steps might include:

  • Testing on more recent versions of perl, then bisecting.
  • Testing using these versions of gcc on other OSes.
  • Testing using these versions of gcc on newer versions of FreeBSD.

@jkeenan jkeenan removed the Closable? We might be able to close this ticket, but we need to check with the reporter label Sep 28, 2022
@tonycoz
Copy link
Contributor

tonycoz commented Sep 29, 2022

I haven't been following this closely, but it appears there is resistance to adding the &, and I don't understand that resistance.

&Errno::EINVAL isn't constant replaced:

tony@venus:.../git/perl5$ perl -MO=Concise -MErrno -e 'print &Errno::EINVAL'
8  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter v ->2
2     <;> nextstate(main 45 -e:1) v:{ ->3
7     <@> print vK ->8
3        <0> pushmark s ->4
6        <1> entersub[t2] lK/AMPER,TARG ->7
-           <1> ex-list lK ->6
4              <0> pushmark s ->5
-              <1> ex-rv2cv sK/AMPER,1 ->-
5                 <#> gv[*Errno::EINVAL] s ->6
-e syntax OK
tony@venus:.../git/perl5$ perl -MO=Concise -MErrno -e 'print Errno::EINVAL'
6  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter v ->2
2     <;> nextstate(main 45 -e:1) v:{ ->3
5     <@> print vK ->6
3        <0> pushmark s ->4
4        <$> const[IV 22] s*/FOLD ->5
-e syntax OK

Errno::EINVAL() is constant replaced and doesn't result in a compile-time strict error if there's no definition.

I suspect the resistance is due to the cause being an already fixed bug (which I believe Devel::PatchPerl patches).

Note the bug is Errno not providing EINVAL on a system that defines that value.

@jkeenan
Copy link
Contributor

jkeenan commented Sep 30, 2022

Errno::EINVAL() is constant replaced and doesn't result in a compile-time strict error if there's no definition.

I suspect the resistance is due to the cause being an already fixed bug (which I believe Devel::PatchPerl patches).

Note the bug is Errno not providing EINVAL on a system that defines that value.

  1. @tonycoz, what can we do about that Errno problem?
  2. I note in passing that I am able to reproduce the bug on FreeBSD-12 as well.
$ uname -mrs
FreeBSD 12.3-RELEASE-p1 amd64
$ git describe
v5.20.0
$ ./perl -Ilib -V:config_args
config_args='-des -Dusedevel -Dcc=gcc10';
$ ./perl -Ilib -e 'use IO::Socket;'
Bareword "Errno::EINVAL" not allowed while "strict subs" in use at lib/IO/Socket.pm line 135.
Compilation failed in require at -e line 1.
BEGIN failed--compilation aborted at -e line 1.

@tonycoz
Copy link
Contributor

tonycoz commented Sep 30, 2022

  • @tonycoz, what can we do about that Errno problem?

Release Errno on CPAN and make IO released on CPAN depend on a sufficiently recent version.

We could also change IO to use the Errno::EINVAL() form, which will fix this specific issue (but not all issues).

The case reported here is only called on Win32 (it's a compilation error), but some of the XS specifically sets errno to EINVAL, and we test for that result, so there's other problems without a valid EINVAL too.

  • I note in passing that I am able to reproduce the bug on FreeBSD-12 as well

Yes, it's a problem with handling output from gcc, IIRC, it's not operating system specific.

@jkeenan
Copy link
Contributor

jkeenan commented Oct 2, 2022

In #20355 (comment), @drq883, the original poster, reported getting a compilation error when (to oversimplify somewhat) he attempted to use IO::Socket; on a perl-5.20.2 built with gcc-10.3.0 on FreeBSD-13.1. He did not get this compilation error when the same code was run on the same operating system but with a perl-5.20.2 built with clang13.

Given that the perl version in question is eight years old and out of support, we're not going to patch the perl source code -- but we do want to understand the problem as best we can.

I had a FreeBSD-13 VM available, so I built perl-5.20.2 using my customary clang (version 10) and ran a program in which I did nothing other than attempt to use IO::Socket;. I could not reproduce the OP's problem, nor could I do so with clang11.

@Grinnz wondered if the problem was related to one corrected in #14491 in February 2015. As we'll see below, his hunch was correct.

The OP and I were each able to demonstrate that the problem was specific to gcc. I was able to demonstrate that whether one built with threads or not was irrelevant.

Working on FreeBSD-12 I was able to reproduce the problem with a perl-5.20.0 but not with perl-5.22.0 released about one year earlier. So the question then became: At what point in the 5.21 development cycle, building perl with a relatively recent gcc (10), did the compilation error no longer appear?

Bisection points to this commit:

commit 816b056ffb99ae54642320e20dc30a59fd1effef
Author: Petr Písař <[email protected]>
Date:   Wed Feb 11 15:46:37 2015 +0100
Commit:     Tony Cook <[email protected]>
CommitDate: Tue Feb 17 10:21:43 2015 +1100

    Fix Errno.pm generation for gcc-5.0
    
    gcc-5.0 -E interleaves now line numbers with expended macros, so that
    the generated errno.c will be preprocessed to
    
    EBFONT => [[
               59
                    ]]
    
    which is hard to parse in in line-based reader.
    
    So use -P option with gcc >= 5.0. Global -P usage would break makedepend,
    global -ftrack-macro-expansion=0 would break lib/h2ph.t.
    
    RT#123784

ext/Errno/Errno_pm.PL | 23 +++++++++++++++++------
1 file changed, 17 insertions(+), 6 deletions(-)

I personally don't have any gcc installed between versions 5 and 8 inclusive. Our dromedary test server has older perl executables built by @Tux using either gcc-4.4.7 or gcc-4.8.5. My hunch is that gcc-5 introduced a problem, we worked around it 816b056, and that at some later point gcc may have fixed the bug. But this is all very difficult to keep straight in one's mind.

@tonycoz
Copy link
Contributor

tonycoz commented Oct 5, 2022

I personally don't have any gcc installed between versions 5 and 8 inclusive. Our dromedary test server has older perl executables built by Tux using either gcc-4.4.7 or gcc-4.8.5. My hunch is that gcc-5 introduced a problem, we worked around it 816b056, and that at some later point gcc may have fixed the bug. But this is all very difficult to keep straight in one's mind.

It wasn't and isn't a bug in gcc.

The problem was that with this input:

#include <errno.h>

"EINVAL" [[ EINVAL ]]
"EAGAIN" [[ EAGAIN ]]

The gcc cpp went from producing output like this:

# irrelevant noise here
# 37 "/usr/include/errno.h" 3 4
extern int *__errno_location (void) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__));

# 3 "testcpp.c"
"EINVAL" [[ 22 ]]
"EAGAIN" [[ 11 ]]

which the Errno_pm.PL parser could parse, to code like:

# irrelevant noise here
# 37 "/usr/include/errno.h" 3 4
extern int *__errno_location (void) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__));
# 52 "/usr/include/errno.h" 3 4

# 2 "testcpp.c" 2


# 3 "testcpp.c"
"EINVAL" [[ 
# 3 "testcpp.c" 3 4
           22 
# 3 "testcpp.c"
                  ]]
"EAGAIN" [[ 
# 4 "testcpp.c" 3 4
           11 
# 4 "testcpp.c"
                  ]]

which the Errno_pm.PL parser could not parse, which left use with an empty list of error constants.

Both outputs are completely valid for a C preprocessor - they form a valid input to a C compiler.

You can see this happen with a recent gcc if you comment out the assignment in:

	    # GCC 5.0 interleaves expanded macros with line numbers breaking
	    # each line into multiple lines. RT#123784
	    $inhibit_linemarkers = ' -P';

so it hasn't been "fixed" in gcc - it wasn't broken.

So the fix for older perls is to use a fixed Errno_pm.PL, but that's in ext/ so we don't put it on CPAN. If we do put it on CPAN, older perls can get the fix, and IO can depend on that fix and this problem will no longer occur, at least for systems that define EINVAL, which even Win32 does.

An alternative is to use Devel::PatchPerl, which includes the fix, but IO can't depend on that declaratively, though it could check at Makefile.PL time that Errno::EINVAL is available.

@jkeenan
Copy link
Contributor

jkeenan commented Jan 10, 2023

I personally don't have any gcc installed between versions 5 and 8 inclusive. Our dromedary test server has older perl executables built by Tux using either gcc-4.4.7 or gcc-4.8.5. My hunch is that gcc-5 introduced a problem, we worked around it 816b056, and that at some later point gcc may have fixed the bug. But this is all very difficult to keep straight in one's mind.

It wasn't and isn't a bug in gcc.

The problem was that with this input:

#include <errno.h>

"EINVAL" [[ EINVAL ]]
"EAGAIN" [[ EAGAIN ]]

The gcc cpp went from producing output like this:

# irrelevant noise here
# 37 "/usr/include/errno.h" 3 4
extern int *__errno_location (void) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__));

# 3 "testcpp.c"
"EINVAL" [[ 22 ]]
"EAGAIN" [[ 11 ]]

which the Errno_pm.PL parser could parse, to code like:

# irrelevant noise here
# 37 "/usr/include/errno.h" 3 4
extern int *__errno_location (void) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__const__));
# 52 "/usr/include/errno.h" 3 4

# 2 "testcpp.c" 2


# 3 "testcpp.c"
"EINVAL" [[ 
# 3 "testcpp.c" 3 4
           22 
# 3 "testcpp.c"
                  ]]
"EAGAIN" [[ 
# 4 "testcpp.c" 3 4
           11 
# 4 "testcpp.c"
                  ]]

which the Errno_pm.PL parser could not parse, which left use with an empty list of error constants.

Both outputs are completely valid for a C preprocessor - they form a valid input to a C compiler.

You can see this happen with a recent gcc if you comment out the assignment in:

	    # GCC 5.0 interleaves expanded macros with line numbers breaking
	    # each line into multiple lines. RT#123784
	    $inhibit_linemarkers = ' -P';

so it hasn't been "fixed" in gcc - it wasn't broken.

So the fix for older perls is to use a fixed Errno_pm.PL, but that's in ext/ so we don't put it on CPAN. If we do put it on CPAN, older perls can get the fix, and IO can depend on that fix and this problem will no longer occur, at least for systems that define EINVAL, which even Win32 does.

An alternative is to use Devel::PatchPerl, which includes the fix, but IO can't depend on that declaratively, though it could check at Makefile.PL time that Errno::EINVAL is available.

@tonycoz, what changes, if any, do we need to make in the core distribution to resolve this ticket?

tonycoz added a commit to tonycoz/perl5 that referenced this issue Jan 12, 2023
I was tempted to look for a minimal version to depend on that
implements the gcc switches that provoked this change, but other
recent changes are also useful.

Fixes Perl#20355
@tonycoz
Copy link
Contributor

tonycoz commented Jan 12, 2023

@tonycoz, what changes, if any, do we need to make in the core distribution to resolve this ticket?

The most reasonable I think would be to move Errno from ext to dist, release that on CPAN, and make IO depend on Errno.

Other options:

  • make IO/Makefile.PL reject broken Errno: recovering this could be painful, the user needs to rebuild perl to recover
  • make IO optionally depend on whether Errno::EINVAL is defined: this ships an IO that doesn't do the error handling we test with.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants