Skip to content
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

commit d2e38af7 exhausts swap space on FreeBSD #16340

Closed
p5pRT opened this issue Dec 25, 2017 · 19 comments
Closed

commit d2e38af7 exhausts swap space on FreeBSD #16340

p5pRT opened this issue Dec 25, 2017 · 19 comments

Comments

@p5pRT
Copy link

p5pRT commented Dec 25, 2017

Migrated from rt.perl.org#132651 (status was 'open')

Searchable as RT132651$

@p5pRT
Copy link
Author

p5pRT commented Dec 25, 2017

From @jkeenan

This afternoon while conducting a smoke test run in my normal manner on
FreeBSD-11.0, I noticed that I was getting messages on STDERR saying
"swap_pager​: out of swap space". I would then get another message
indicating that the kernel was killing a particular perl PID.

I had never seen such messages before in this VM. Since I had to go out
to a family dinner, I didn't have time to diagnose or correct the
problem. When I came back six hours later, I saw that I had gotten
failures in 3 of the 4 variants within the smoke test run in this file​:
./dist/PathTools/t/cwd_enoent.t. (http​://perl5.test-smoke.org/report/61071)

I had never seen problems with this file before (but, as it turns out,
that's in part because it's a brand new file).

Usually when I have a test failure in one of my FreeBSD smokers, it's
due to an intermittent resource constraint and I can get a PASS on the
file by running it manually. However, when I tried to do that here, I
got an endless stream of the following on STDERR​:

$ cd t;./perl harness -v ../dist/PathTools/t/cwd_enoent.t; cd -
pwd​: .​: No such file or directory # <-- endlessly until Ctrl-C

This output appears before any other output from the test file. Indeed,
I never got to see any other output from this test file. I have
reproduced this problem in​:

* the perl-current directory of my smoke test rig on FreeBSD-11.0;
* in a blead of build in my regular git checkout on FreeBSD-11.0;
* in a blead of build in my regular git checkout on FreeBSD-10.3;

The errant file was only committed to blead earlier today​:

#####
commit d2e38af
Author​: Zefram <zefram@​fysh.org>
Date​: Sun Dec 24 11​:09​:54 2017 +0000

  correct error returns from _perl_abs_path()
#####

The commit should be reverted ASAP and tested in a branch on various
OSes until its problems are well understood.

Thank you very much.
Jim Keenan

@p5pRT
Copy link
Author

p5pRT commented Dec 25, 2017

From @jkeenan

Summary of my perl5 (revision 5 version 27 subversion 8) configuration​:
  Commit id​: dfc19b6
  Platform​:
  osname=freebsd
  osvers=10.3-release
  archname=amd64-freebsd-thread-multi
  uname='freebsd localhost 10.3-release freebsd 10.3-release #0 r297264​: fri mar 25 02​:10​:02 utc 2016 root@​releng1.nyi.freebsd.org​:usrobjusrsrcsysgeneric amd64 '
  config_args='-des -Dusedevel -Duseithreads -Doptimize=-O2 -pipe -fstack-protector -fno-strict-aliasing'
  hint=recommended
  useposix=true
  d_sigaction=define
  useithreads=define
  usemultiplicity=define
  use64bitint=define
  use64bitall=define
  uselongdouble=undef
  usemymalloc=n
  default_inc_excludes_dot=define
  bincompat5005=undef
  Compiler​:
  cc='cc'
  ccflags ='-DHAS_FPSETMASK -DHAS_FLOATINGPOINT_H -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_FORTIFY_SOURCE=2'
  optimize='-O2 -pipe -fstack-protector -fno-strict-aliasing'
  cppflags='-DHAS_FPSETMASK -DHAS_FLOATINGPOINT_H -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
  ccversion=''
  gccversion='4.2.1 Compatible FreeBSD Clang 3.4.1 (tags/RELEASE_34/dot1-final 208032)'
  gccosandvers=''
  intsize=4
  longsize=8
  ptrsize=8
  doublesize=8
  byteorder=12345678
  doublekind=3
  d_longlong=define
  longlongsize=8
  d_longdbl=define
  longdblsize=16
  longdblkind=3
  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/include/clang/3.4.1 /usr/lib
  libs=-lpthread -lgdbm -lm -lcrypt -lutil -lelf
  perllibs=-lpthread -lm -lcrypt -lutil -lelf
  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_COPY_ON_WRITE
  PERL_DONT_CREATE_GVSV
  PERL_IMPLICIT_CONTEXT
  PERL_MALLOC_WRAP
  PERL_OP_PARENT
  PERL_PRESERVE_IVUV
  PERL_USE_DEVEL
  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_LOCALE_TIME
  USE_PERLIO
  USE_PERL_ATOF
  USE_REENTRANT_API
  Built under freebsd
  Compiled at Dec 24 2017 21​:26​:14
  %ENV​:
  PERL2DIR="/home/jkeenan/gitwork/perl2"
  PERL_WORKDIR="/home/jkeenan/gitwork/perl"
  @​INC​:
  lib
  /usr/local/lib/perl5/site_perl/5.27.8/amd64-freebsd-thread-multi
  /usr/local/lib/perl5/site_perl/5.27.8
  /usr/local/lib/perl5/5.27.8/amd64-freebsd-thread-multi
  /usr/local/lib/perl5/5.27.8

@p5pRT
Copy link
Author

p5pRT commented Dec 25, 2017

From zefram@fysh.org

I've disabled that test in commit 06c214d.

-zefram

@p5pRT
Copy link
Author

p5pRT commented Dec 25, 2017

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Dec 25, 2017

From zefram@fysh.org

James E Keenan wrote​:

$ cd t;./perl harness -v ../dist/PathTools/t/cwd_enoent.t; cd -
pwd​: .​: No such file or directory # <-- endlessly until Ctrl-C

This is curious. It is not terribly surprising that pwd(1) would
get involved somewhere, but that it would loop is very strange.
Although PathTools does have some logic to invoke pwd(1), it doesn't
have anything that would loop, and in any case it seems impossible for
that to be invoked on BSD. So I think the use of pwd(1) and the loop
must both be coming from libc, probably in getcwd(3).

First I'd like to determine exactly where this happens. For it to precede
all other output from the test, this cannot happen any later than the
call to Cwd​::getcwd(), but there is a bit of earlier logic that could
possibly invoke it. Please run this on a BSD that exhibits the failure​:

$ perl -MFile​::Temp=tempdir -MCwd=getcwd -lwe '$tmp = tempdir(CLEANUP => 1); print "aa $tmp"; mkdir("$tmp/testdir") or die; print "bb"; chdir("$tmp/testdir") or die; print "cc"; rmdir("$tmp/testdir") or die; print "dd"; $p = getcwd() // "undef"; print "ee $p"; chdir($tmp) or die; print "ff"'

This doesn't require a PathTools that exhibits the test failure​: the
actual code change in the commit that added the test isn't getting
reached. Also, please show the HAS_GETCWD setting from a recent perl
build on the same system.

If the above test code gets as far as outputting "ee" but not "ff"
(which is quite likely), it would also be interesting to see how the
pure Perl version of getcwd() performs. To do this, change 'getcwd()'
to 'Cwd​::_perl_abs_path(".")' in the test case. This test would be
affected by the version of PathTools, but not in a way that seriously
affects the interpretation.

-zefram

@p5pRT
Copy link
Author

p5pRT commented Dec 25, 2017

From @jkeenan

On Mon, 25 Dec 2017 09​:13​:16 GMT, zefram@​fysh.org wrote​:

James E Keenan wrote​:

$ cd t;./perl harness -v ../dist/PathTools/t/cwd_enoent.t; cd -
pwd​: .​: No such file or directory # <-- endlessly until Ctrl-C

This is curious. It is not terribly surprising that pwd(1) would
get involved somewhere, but that it would loop is very strange.

Here's what I was able to determine last night. (I'll try your suggestions later today.)

1. The file loops over 2 values. If I comment out 'perl' and loop over 'regular', everything is fine.

#####
$ ./perl -Ilib ~/learn/perl/p5p/enoent.pl
1..8
XXX​: type is currently <regular>
ok 1 - regular getcwd result on non-existent directory
ok 2 - regular getcwd errno on non-existent directory
ok 3 - regular abs_path result on non-existent directory
ok 4 - regular abs_path errno on non-existent directory
# Looks like you planned 8 tests but ran 4.
#####

2. If I comment out 'regular', then comment out every line inside the loop, then un-comment one line at a time from the top down, everything is fine up to this point​:

#####
foreach my $type (qw(perl)) {
  SKIP​: {
  skip "_perl_abs_path() not expected to work", 4
  if $type eq "perl" &&
  !(($Config{prefix} =~ m/\//) &amp;&amp; $^O ne "cygwin");
print STDERR "XXX​: type is currently <$type>\n";
  no warnings "redefine";
  local *Cwd​::abs_path = \&Cwd​::_perl_abs_path if $type eq "perl";
  local *Cwd​::getcwd = \&Cwd​::_perl_getcwd if $type eq "perl";
  my($res, $eno);
  $! = 0;
# $res = Cwd​::getcwd();
... # commented-out balance of loop
#####
$ ./perl -Ilib ~/learn/perl/p5p/enoent.pl
1..8
XXX​: type is currently <perl>
# No tests run!
#####

3. But when I un-comment the very next line, I get the swap-eating output​:

#####
foreach my $type (qw(perl)) {
  SKIP​: {
  skip "_perl_abs_path() not expected to work", 4
  if $type eq "perl" &&
  !(($Config{prefix} =~ m/\//) &amp;&amp; $^O ne "cygwin");
print STDERR "XXX​: type is currently <$type>\n";
  no warnings "redefine";
  local *Cwd​::abs_path = \&Cwd​::_perl_abs_path if $type eq "perl";
  local *Cwd​::getcwd = \&Cwd​::_perl_getcwd if $type eq "perl";
  my($res, $eno);
  $! = 0;
  $res = Cwd​::getcwd(); # <-- line where things go haywire when $type eq 'perl'
# $eno = 0+$!;
... # comment out balance of loop
#####
$ ./perl -Ilib ~/learn/perl/p5p/enoent.pl
pwd​: .​: No such file or directory
pwd​: .​: No such file or directory
pwd​: .​: No such file or directory
pwd​: .​: No such file or directory
pwd​: .​: No such file or directory
^C
#####

More to come later. Thank you for your prompt response.

--
James E Keenan (jkeenan@​cpan.org)

@p5pRT
Copy link
Author

p5pRT commented Dec 25, 2017

From @jkeenan

On Mon, 25 Dec 2017 09​:13​:16 GMT, zefram@​fysh.org wrote​:

James E Keenan wrote​:

$ cd t;./perl harness -v ../dist/PathTools/t/cwd_enoent.t; cd -
pwd​: .​: No such file or directory # <-- endlessly until Ctrl-C

This is curious. It is not terribly surprising that pwd(1) would
get involved somewhere, but that it would loop is very strange.
Although PathTools does have some logic to invoke pwd(1), it doesn't
have anything that would loop, and in any case it seems impossible for
that to be invoked on BSD. So I think the use of pwd(1) and the loop
must both be coming from libc, probably in getcwd(3).

First I'd like to determine exactly where this happens. For it to
precede
all other output from the test, this cannot happen any later than the
call to Cwd​::getcwd(), but there is a bit of earlier logic that could
possibly invoke it. Please run this on a BSD that exhibits the
failure​:

$ perl -MFile​::Temp=tempdir -MCwd=getcwd -lwe '$tmp = tempdir(CLEANUP
=> 1); print "aa $tmp"; mkdir("$tmp/testdir") or die; print "bb";
chdir("$tmp/testdir") or die; print "cc"; rmdir("$tmp/testdir") or
die; print "dd"; $p = getcwd() // "undef"; print "ee $p"; chdir($tmp)
or die; print "ff"'

#####
$ perl -MFile​::Temp=tempdir -MCwd=getcwd -lwe '$tmp = tempdir(CLEANUP => 1); print "aa $tmp"; mkdir("$tmp/testdir") or die; print "bb"; chdir("$tmp/testdir") or die; print "cc"; rmdir("$tmp/testdir") or die; print "dd"; $p = getcwd() // "undef"; print "ee $p"; chdir($tmp) or die; print "ff"'
aa /tmp/tjwG3_xzLJ
bb
cc
dd
ee undef
ff
#####

This doesn't require a PathTools that exhibits the test failure​: the
actual code change in the commit that added the test isn't getting
reached. Also, please show the HAS_GETCWD setting from a recent perl
build on the same system.

From config.h​:
#####
/* HAS_GETCWD​:
* This symbol, if defined, indicates that the getcwd routine is
* available to get the current working directory.
*/
#define HAS_GETCWD /**/
#####
$ grep -in GETCWD config.sh
258​:d_getcwd='define'
#####

If the above test code gets as far as outputting "ee" but not "ff"
(which is quite likely), it would also be interesting to see how the
pure Perl version of getcwd() performs. To do this, change 'getcwd()'
to 'Cwd​::_perl_abs_path(".")' in the test case. This test would be
affected by the version of PathTools, but not in a way that seriously
affects the interpretation.

#####
foreach my $type (qw(regular perl)) {
  SKIP​: {
  skip "_perl_abs_path() not expected to work", 4
  if $type eq "perl" &&
  !(($Config{prefix} =~ m/\//) &amp;&amp; $^O ne "cygwin");
  no warnings "redefine";
  local *Cwd​::abs_path = \&Cwd​::_perl_abs_path if $type eq "perl";
# local *Cwd​::getcwd = \&Cwd​::_perl_getcwd if $type eq "perl";
  local *Cwd​::getcwd = \&Cwd​::_perl_abs_path('.') if $type eq "perl";
  my($res, $eno);
  $! = 0;
  $res = Cwd​::getcwd(); # <-- line where things go haywire when $type eq 'perl'
  $eno = 0+$!;
  is $res, undef, "$type getcwd result on non-existent directory";
  is $eno, ENOENT, "$type getcwd errno on non-existent directory";
  $! = 0;
  $res = Cwd​::abs_path(".");
  $eno = 0+$!;
  is $res, undef, "$type abs_path result on non-existent directory";
  is $eno, ENOENT, "$type abs_path errno on non-existent directory";
  }
}
#####
$ ./perl -Ilib ~/learn/perl/p5p/enoent.pl
1..8
XXX​: type is currently <regular>
ok 1 - regular getcwd result on non-existent directory
ok 2 - regular getcwd errno on non-existent directory
ok 3 - regular abs_path result on non-existent directory
ok 4 - regular abs_path errno on non-existent directory
XXX​: type is currently <perl>
pwd​: .​: No such file or directory
ok 5 - perl getcwd result on non-existent directory
ok 6 - perl getcwd errno on non-existent directory
pwd​: .​: No such file or directory
not ok 7 - perl abs_path result on non-existent directory
# Failed test 'perl abs_path result on non-existent directory'
# at /home/jkeenan/learn/perl/p5p/enoent.pl line 39.
# got​: '/'
# expected​: undef
ok 8 - perl abs_path errno on non-existent directory
Finished!
# Looks like you failed 1 test of 8.
#####

-zefram

--
James E Keenan (jkeenan@​cpan.org)

@p5pRT
Copy link
Author

p5pRT commented Dec 25, 2017

From zefram@fysh.org

James E Keenan via RT wrote​:

1. The file loops over 2 values. If I comment out 'perl' and loop over
'regular', everything is fine.

Huh, so apparently getting no other test output was a red herring.
The problem isn't in libc​: your other message showed the XS getcwd()
using libc's getcwd() and producing the right result. The problem is
in the Perl code, evidently in _perl_abs_path().

I think I understand it now. If _perl_abs_path() fails to
opendir("./..") then it does

  return File​::Spec->rel2abs( $start, _backtick_pwd() );

_backtick_pwd() invokes pwd(1), which would explain getting an error
message from it. File​::Spec​::Unix->rel2abs() then internally, given the
empty string that it gets from the failing pwd(1), calls Cwd​::getcwd().
Since we've aliased that to the Perl version, there's an infinite
recursion.

Can you confirm that that's the path being taken through the code?

I think the use of File​::Spec->rel2abs from _perl_abs_path() is a bad
idea, and should be replaced with a simple error return.

-zefram

@p5pRT
Copy link
Author

p5pRT commented Dec 26, 2017

From @jkeenan

On Mon, 25 Dec 2017 19​:09​:38 GMT, zefram@​fysh.org wrote​:

James E Keenan via RT wrote​:

1. The file loops over 2 values. If I comment out 'perl' and loop over
'regular', everything is fine.

Huh, so apparently getting no other test output was a red herring.
The problem isn't in libc​: your other message showed the XS getcwd()
using libc's getcwd() and producing the right result. The problem is
in the Perl code, evidently in _perl_abs_path().

I think I understand it now. If _perl_abs_path() fails to
opendir("./..") then it does

return File&#8203;::Spec\->rel2abs\( $start\, \_backtick\_pwd\(\) \);

_backtick_pwd() invokes pwd(1), which would explain getting an error
message from it. File​::Spec​::Unix->rel2abs() then internally, given the
empty string that it gets from the failing pwd(1), calls Cwd​::getcwd().
Since we've aliased that to the Perl version, there's an infinite
recursion.

Can you confirm that that's the path being taken through the code?

I wasn't quite sure of how you wanted me to proceed. See the attachment for some debugging output from './perl -Ilib -d ./dist/PathTools/t/cwd_enoent.t' on FreeBSD-10.3.

I think the use of File​::Spec->rel2abs from _perl_abs_path() is a bad
idea, and should be replaced with a simple error return.

-zefram

--
James E Keenan (jkeenan@​cpan.org)

@p5pRT
Copy link
Author

p5pRT commented Dec 26, 2017

From @jkeenan

Cwd​::_perl_abs_path(lib/Cwd.pm​:422)​:
422​: unless (opendir(PARENT, $dotdots))
423​: {
  DB<6>
Cwd​::_perl_abs_path(lib/Cwd.pm​:425)​:
425​: require File​::Spec;
  DB<6>
Cwd​::_perl_abs_path(lib/Cwd.pm​:426)​:
426​: return File​::Spec->rel2abs( $start, _backtick_pwd() );
  DB<6> s
Cwd​::_backtick_pwd(lib/Cwd.pm​:201)​: my @​localize = grep exists $ENV{$_}, qw(PATH IFS CDPATH ENV BASH_ENV) if $^O ne "amigaos";
  DB<6> n
Cwd​::_backtick_pwd(lib/Cwd.pm​:202)​: local @​ENV{@​localize} if @​localize;
  DB<6>
Cwd​::_backtick_pwd(lib/Cwd.pm​:204)​: my $cwd = `$pwd_cmd`;
  DB<6>
pwd​: .​: No such file or directory
Cwd​::_backtick_pwd(lib/Cwd.pm​:206)​: local $/ = "\n";
  DB<6> x $cwd
0 ''
  DB<7> n
File​::Spec​::Unix​::rel2abs(lib/File/Spec/Unix.pm​:502)​:
502​: my ($self,$path,$base ) = @​_;
  DB<7>
File​::Spec​::Unix​::rel2abs(lib/File/Spec/Unix.pm​:505)​:
505​: if ( ! $self->file_name_is_absolute( $path ) ) {
  DB<7> x $path
0 '.'
  DB<8> s
File​::Spec​::Unix​::file_name_is_absolute(lib/File/Spec/Unix.pm​:244)​:
244​: my ($self,$file) = @​_;
  DB<8> n
File​::Spec​::Unix​::file_name_is_absolute(lib/File/Spec/Unix.pm​:245)​:
245​: return scalar($file =~ m​:^/​:s);
  DB<8>
File​::Spec​::Unix​::rel2abs(lib/File/Spec/Unix.pm​:507)​:
507​: if ( !defined( $base ) || $base eq '' ) {
  DB<8>
File​::Spec​::Unix​::rel2abs(lib/File/Spec/Unix.pm​:508)​:
508​: $base = Cwd​::getcwd();
  DB<8> s
Cwd​::_perl_getcwd(lib/Cwd.pm​:256)​: abs_path('.');
  DB<8> s
Cwd​::_perl_abs_path(lib/Cwd.pm​:385)​:
385​: my $start = @​_ ? shift : '.';
  DB<8> n
Cwd​::_perl_abs_path(lib/Cwd.pm​:386)​:
386​: my($dotdots, $cwd, @​pst, @​cst, $dir, @​tst);
  DB<8>
Cwd​::_perl_abs_path(lib/Cwd.pm​:388)​:
388​: unless (@​cst = stat( $start ))
389​: {
  DB<8>
Cwd​::_perl_abs_path(lib/Cwd.pm​:393)​:
393​: unless (-d _) {
  DB<8>
Cwd​::_perl_abs_path(lib/Cwd.pm​:415)​:
415​: $cwd = '';
  DB<8> n
Cwd​::_perl_abs_path(lib/Cwd.pm​:416)​:
416​: $dotdots = $start;
417​: do
  DB<8>
Cwd​::_perl_abs_path(lib/Cwd.pm​:418)​:
418​: {
  DB<8>
Cwd​::_perl_abs_path(lib/Cwd.pm​:419)​:
419​: $dotdots .= '/..';
  DB<8>
Cwd​::_perl_abs_path(lib/Cwd.pm​:420)​:
420​: @​pst = @​cst;
  DB<8>
Cwd​::_perl_abs_path(lib/Cwd.pm​:421)​:
421​: local *PARENT;
  DB<8>
Cwd​::_perl_abs_path(lib/Cwd.pm​:422)​:
422​: unless (opendir(PARENT, $dotdots))
423​: {
  DB<8>
Cwd​::_perl_abs_path(lib/Cwd.pm​:425)​:
425​: require File​::Spec;
  DB<8>
Cwd​::_perl_abs_path(lib/Cwd.pm​:426)​:
426​: return File​::Spec->rel2abs( $start, _backtick_pwd() );
  DB<8> s
Cwd​::_backtick_pwd(lib/Cwd.pm​:201)​: my @​localize = grep exists $ENV{$_}, qw(PATH IFS CDPATH ENV BASH_ENV) if $^O ne "amigaos";
  DB<8> n
Cwd​::_backtick_pwd(lib/Cwd.pm​:202)​: local @​ENV{@​localize} if @​localize;
  DB<8>
Cwd​::_backtick_pwd(lib/Cwd.pm​:204)​: my $cwd = `$pwd_cmd`;
  DB<8>
pwd​: .​: No such file or directory
Cwd​::_backtick_pwd(lib/Cwd.pm​:206)​: local $/ = "\n";
  DB<8>
Cwd​::_backtick_pwd(lib/Cwd.pm​:208)​: chomp($cwd) if defined $cwd;
  DB<8>
Cwd​::_backtick_pwd(lib/Cwd.pm​:209)​: $cwd;
  DB<8>
File​::Spec​::Unix​::rel2abs(lib/File/Spec/Unix.pm​:502)​:
502​: my ($self,$path,$base ) = @​_;
  DB<8>
File​::Spec​::Unix​::rel2abs(lib/File/Spec/Unix.pm​:505)​:
505​: if ( ! $self->file_name_is_absolute( $path ) ) {
  DB<8>
File​::Spec​::Unix​::rel2abs(lib/File/Spec/Unix.pm​:507)​:
507​: if ( !defined( $base ) || $base eq '' ) {
  DB<8>
File​::Spec​::Unix​::rel2abs(lib/File/Spec/Unix.pm​:508)​:
508​: $base = Cwd​::getcwd();
  DB<8>
pwd​: .​: No such file or directory
pwd​: .​: No such file or directory
...
pwd​: .​: No such file or directory
File​::Spec​::Unix​::file_name_is_absolute(lib/File/Spec/Unix.pm​:244)​:
244​: my ($self,$file) = @​_;
1000 levels deep in subroutine calls!
  DB<8> File​::Spec​::Unix​::file_name_is_absolute(lib/File/Spec/Unix.pm​:245)​:
245​: return scalar($file =~ m​:^/​:s);
  DB<8> File​::Spec​::Unix​::rel2abs(lib/File/Spec/Unix.pm​:507)​:
507​: if ( !defined( $base ) || $base eq '' ) {
999 levels deep in subroutine calls!
  DB<8> File​::Spec​::Unix​::rel2abs(lib/File/Spec/Unix.pm​:508)​:
508​: $base = Cwd​::getcwd();
999 levels deep in subroutine calls!
  DB<8> Cwd​::_perl_getcwd(lib/Cwd.pm​:256)​: abs_path('.');
1000 levels deep in subroutine calls!
  DB<8> pwd​: .​: No such file or directory
pwd​: .​: No such file or directory
pwd​: .​: No such file or directory
... [snip]
pwd​: .​: No such file or directory
pwd​: .​: No such file or directory
^CCwd​::_backtick_pwd(lib/Cwd.pm​:206)​: local $/ = "\n";
  DB<8>

@p5pRT
Copy link
Author

p5pRT commented Dec 26, 2017

From zefram@fysh.org

James E Keenan via RT wrote​:

See the attachment for some debugging output

That confirms my suspicion, thanks. Fixed in commit
815d526.

-zefram

@p5pRT
Copy link
Author

p5pRT commented Dec 26, 2017

From @jkeenan

On Tue, 26 Dec 2017 07​:50​:45 GMT, zefram@​fysh.org wrote​:

James E Keenan via RT wrote​:

See the attachment for some debugging output

That confirms my suspicion, thanks. Fixed in commit
815d526.

-zefram

Thanks. I'm no longer getting infinite loops or exhaustion of swap space on FreeBSD. However, I see that we have a FAIL in this test file being reported on a Cygwin smoke rig. Please see​: http​://perl.develop-help.com/raw/?id=204663

Thank you very much.

--
James E Keenan (jkeenan@​cpan.org)

@p5pRT
Copy link
Author

p5pRT commented Dec 26, 2017

From @eserte

Zefram <zefram@​fysh.org> writes​:

James E Keenan via RT wrote​:

1. The file loops over 2 values. If I comment out 'perl' and loop over
'regular', everything is fine.

Huh, so apparently getting no other test output was a red herring.
The problem isn't in libc​: your other message showed the XS getcwd()
using libc's getcwd() and producing the right result. The problem is
in the Perl code, evidently in _perl_abs_path().

I think I understand it now. If _perl_abs_path() fails to
opendir("./..") then it does

return File&#8203;::Spec\->rel2abs\( $start\, \_backtick\_pwd\(\) \);

_backtick_pwd() invokes pwd(1), which would explain getting an error
message from it. File​::Spec​::Unix->rel2abs() then internally, given the
empty string that it gets from the failing pwd(1), calls Cwd​::getcwd().
Since we've aliased that to the Perl version, there's an infinite
recursion.

Can you confirm that that's the path being taken through the code?

I also see the error on a FreeBSD 12 system (any perl), and it's indeed
an endless loop here​:

  $ = File​::Spec​::Unix​::_cwd('File​::Spec') called from file '/usr/local/lib/perl5/5.24/mach/File/Spec/Unix.pm' line 522
  $ = File​::Spec​::Unix​::rel2abs('File​::Spec', ., '') called from file '/usr/local/lib/perl5/5.24/mach/Cwd.pm' line 458
  $ = Cwd​::_perl_abs_path(.) called from file '/usr/local/lib/perl5/5.24/mach/Cwd.pm' line 284
  $ = Cwd​::_perl_getcwd() called from file '/tmp/cwd_enoent.t' line 29

I think the use of File​::Spec->rel2abs from _perl_abs_path() is a bad
idea, and should be replaced with a simple error return.

Probably rewriting the lines like this​:

  require File​::Spec;
  my $base = _backtick_pwd();
  return '' if !defined $base;
  return File​::Spec->rel2abs( $start, $base );

(untested) should suffice.

Regards,
  Slaven

--
Slaven Rezic - slaven <at> rezic <dot> de

  Berlin Perl Mongers - http​://berlin.pm.org

@p5pRT
Copy link
Author

p5pRT commented Dec 26, 2017

From @eserte

"James E Keenan via RT" <perlbug-followup@​perl.org> writes​:

On Tue, 26 Dec 2017 07​:50​:45 GMT, zefram@​fysh.org wrote​:

James E Keenan via RT wrote​:

See the attachment for some debugging output

That confirms my suspicion, thanks. Fixed in commit
815d526.

-zefram

Thanks. I'm no longer getting infinite loops or exhaustion of swap
space on FreeBSD. However, I see that we have a FAIL in this test file
being reported on a Cygwin smoke rig. Please see​:
http​://perl.develop-help.com/raw/?id=204663

I guess that on some systems it's not possible to remove a directory
which is a current working directory for some (or this) process. In
another project I do something similar and have to skip this test on
some systems​:

  SKIP​: {
  my $success = rmdir "$tempdir/another_dir";
  skip "Cannot test - cannot remove active directory", 1
  if (!$success &&
  ( $!{EINVAL} # seen on Solaris
  || $!{EACCES} # seen on MSWin32
  )
  );
  if (!$success) {
  die "Cannot remove directory​: $!"; # unexpected error
  }
  ...

Regards,
  Slaven

--
Slaven Rezic - slaven <at> rezic <dot> de

  Berlin Perl Mongers - http​://berlin.pm.org

@p5pRT
Copy link
Author

p5pRT commented Dec 26, 2017

From zefram@fysh.org

James E Keenan via RT wrote​:

However, I see that we have a FAIL in this test file being reported on
a Cygwin smoke rig.

That's annoying. The test allows for a platform to veto having an
unlinked cwd, and I'd expect Windows to exercise that veto, but apparently
it's not, so I don't know what arrangement Cygwin actually ends up with.
Apparently it's getting the wrong result from the XS getcwd(), and then
terminating when running the XS abs_path(). I don't see how that could
terminate when getcwd() didn't.

I'd like to see more detail of the test output and the mode of
termination.

-zefram

@p5pRT
Copy link
Author

p5pRT commented Apr 19, 2018

From @iabyn

On Tue, Dec 26, 2017 at 08​:06​:36PM +0000, Zefram wrote​:

James E Keenan via RT wrote​:

However, I see that we have a FAIL in this test file being reported on
a Cygwin smoke rig.

That's annoying. The test allows for a platform to veto having an
unlinked cwd, and I'd expect Windows to exercise that veto, but apparently
it's not, so I don't know what arrangement Cygwin actually ends up with.
Apparently it's getting the wrong result from the XS getcwd(), and then
terminating when running the XS abs_path(). I don't see how that could
terminate when getcwd() didn't.

I'd like to see more detail of the test output and the mode of
termination.

So IIUC, in this ticket, the infinite loop problem has been fixed on
all platforms except Cygwin.

CXan we do anything about that (e.g. skip the test),
and if so can this ticket then be removed from the 5.28 blockers?

--
"I used to be with it, but then they changed what ‘it’ was, and now what
I’m with isn’t it. And what’s ‘it’ seems weird and scary to me."
  -- Grandpa Simpson
(It will happen to you too.)

@p5pRT
Copy link
Author

p5pRT commented Apr 23, 2018

From @iabyn

On Thu, Apr 19, 2018 at 11​:50​:38PM +0100, Dave Mitchell wrote​:

On Tue, Dec 26, 2017 at 08​:06​:36PM +0000, Zefram wrote​:

James E Keenan via RT wrote​:

However, I see that we have a FAIL in this test file being reported on
a Cygwin smoke rig.

That's annoying. The test allows for a platform to veto having an
unlinked cwd, and I'd expect Windows to exercise that veto, but apparently
it's not, so I don't know what arrangement Cygwin actually ends up with.
Apparently it's getting the wrong result from the XS getcwd(), and then
terminating when running the XS abs_path(). I don't see how that could
terminate when getcwd() didn't.

I'd like to see more detail of the test output and the mode of
termination.

So IIUC, in this ticket, the infinite loop problem has been fixed on
all platforms except Cygwin.

CXan we do anything about that (e.g. skip the test),
and if so can this ticket then be removed from the 5.28 blockers?

I see that for (unrelated, I think) reasons, cwd_enoent.t
was disabled by Zefram under Cygwin by 9e783da back on 17 Jan, so
I'm assuming this is no longer a blocker?

--
O Unicef Clearasil!
Gibberish and Drivel!
  -- "Bored of the Rings"

@p5pRT
Copy link
Author

p5pRT commented Apr 25, 2018

From @iabyn

On Mon, Apr 23, 2018 at 01​:21​:40PM +0100, Dave Mitchell wrote​:

I see that for (unrelated, I think) reasons, cwd_enoent.t
was disabled by Zefram under Cygwin by 9e783da back on 17 Jan, so
I'm assuming this is no longer a blocker?

Now unblocked.

--
All wight. I will give you one more chance. This time, I want to hear
no Wubens. No Weginalds. No Wudolf the wed-nosed weindeers.
  -- Life of Brian

@jkeenan
Copy link
Contributor

jkeenan commented Jan 31, 2020

The Cygwin problem is now tracked in #16366. Everything else appears to be resolved. Closing.

@jkeenan jkeenan closed this as completed Jan 31, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants