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

Can't run t/harness with a perl built for gprof #13040

Open
p5pRT opened this issue Jun 20, 2013 · 15 comments
Open

Can't run t/harness with a perl built for gprof #13040

p5pRT opened this issue Jun 20, 2013 · 15 comments

Comments

@p5pRT
Copy link

p5pRT commented Jun 20, 2013

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

Searchable as RT118549$

@p5pRT
Copy link
Author

p5pRT commented Jun 20, 2013

From @nwc10

Created by @nwc10

I've built perl with -pg in the C flags to enabled profiling for gprof.
I can't run t/harness to completion - it bails out like this​:

../cpan/IO-Compress/t/105oneshot-zip-store-only.t ................. ok
../cpan/IO-Compress/t/105oneshot-zip.t ............................ ok
../cpan/IO-Compress/t/106prime-bzip2.t ............................ 267/3823 Can't use an undefined value as an ARRAY reference at ../lib/TAP/Parser/Multiplexer.pm line 139.
make​: *** [test_harness] Error 4

The Perl code in question is this​:

  unless (@​ready) {
  return unless $sel->count;
  @​ready = $sel->can_read;
  }

  my ( $h, $parser, $stash, @​handles ) = @​{ shift @​ready };
  my $result = $parser->next;

With a little bit of annotation​:

Inline Patch
diff --git a/cpan/Test-Harness/lib/TAP/Parser/Multiplexer.pm b/cpan/Test-Harness
index 913aa92..4b7f173 100644
--- a/cpan/Test-Harness/lib/TAP/Parser/Multiplexer.pm
+++ b/cpan/Test-Harness/lib/TAP/Parser/Multiplexer.pm
@@ -132,8 +132,15 @@ sub _iter {
         }

         unless (@ready) {
-            return unless $sel->count;
+           my $count = $sel->count;
+            return unless $count;
             @ready = $sel->can_read;
+           use Devel::Peek;
+           use Data::Dumper;
+           unless (defined $ready[0]) {
+               Dump $count;
+               print Dumper \@ready;
+           }
         }

         my ( $h, $parser, $stash, @handles ) = @{ shift @ready };


I can see that $count is 6, and @ready is empty:

===( 48991;42 468/1750 292/1750 )=================================SV = IV(0x101ea70) at 0x101ea80
  REFCNT = 1
  FLAGS = (PADMY,IOK,pIOK)
  IV = 6
$VAR1 = [];
Can't use an undefined value as an ARRAY reference at ../lib/TAP/Parser/Multiplexer.pm line 146.

strace on that annotated version looks like this​:

read(3, "ok 1175\n", 65536) = 8
select(16, [3 4 5 7 8 9], NULL, NULL, NULL) = 1 (in [3])
select(16, [3 8], NULL, NULL, NULL) = 1 (in [3])
read(3, "ok 1176\n", 65536) = 8
select(16, [3 4 5 7 8 9], NULL, NULL, NULL) = 1 (in [3])
select(16, [3 8], NULL, NULL, NULL) = 1 (in [3])
read(3, "ok 1177\n", 65536) = 8
select(16, [3 4 5 7 8 9], NULL, NULL, NULL) = ? ERESTARTNOHAND (To be restarted)
--- SIGPROF (Profiling timer expired) @​ 0 (0) ---
rt_sigreturn(0x1b) = -1 EINTR (Interrupted system call)
write(2, "SV = ", 5) = 5
write(2, "IV(0x101ea70) at 0x101ea80\n REF"..., 67) = 67
write(2, " IV = 6", 8) = 8
write(2, "\n", 1) = 1
write(1, "$VAR1 = [];\n", 12) = 12
write(2, "Can't use an undefined value as "..., 97) = 97
rt_sigaction(SIGHUP, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGINT, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGQUIT, NULL, {SIG_DFL, [], 0}, 8) = 0

So whose bug is it?

1) pp_sselect, for not restarting on that signal?
2) IO​::Select for returning a contradictory set of results?
3) TAP​::Parser​::Multiplexer, for not coping with this?

Nicholas Clark

Perl Info

Flags:
    category=core
    severity=low

Site configuration information for perl 5.19.1:

Configured by nick at Thu Jun 20 13:27:16 CEST 2013.

Summary of my perl5 (revision 5 version 19 subversion 1) configuration:
  Derived from: e08fc7eabc43f861faa02b59949821de0e73b037
  Platform:
    osname=linux, osvers=2.6.32-5-amd64, archname=x86_64-linux
    uname='linux gcc20 2.6.32-5-amd64 #1 smp mon jan 16 16:22:28 utc 2012 x86_64 gnulinux '
    config_args='-des -Dusedevel -Accflags=-pg -Aldflags=-pg -Alddlflags=-pg -shared'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=undef, usemultiplicity=undef
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=define, use64bitall=define, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-pg -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O2',
    cppflags='-pg -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
    ccversion='', gccversion='4.4.5', 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 =' -pg -fstack-protector -L/usr/local/lib'
    libpth=/usr/local/lib /lib/../lib /usr/lib/../lib /lib /usr/lib /lib64 /usr/lib64
    libs=-lnsl -ldl -lm -lcrypt -lutil -lc
    perllibs=-lnsl -ldl -lm -lcrypt -lutil -lc
    libc=/lib/libc-2.11.3.so, so=so, useshrplib=false, libperl=libperl.a
    gnulibc_version='2.11.3'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fPIC', lddlflags=' -pg -shared -L/usr/local/lib -fstack-protector'

Locally applied patches:
    


@INC for perl 5.19.1:
    lib
    /usr/local/lib/perl5/site_perl/5.19.1/x86_64-linux
    /usr/local/lib/perl5/site_perl/5.19.1
    /usr/local/lib/perl5/5.19.1/x86_64-linux
    /usr/local/lib/perl5/5.19.1
    .


Environment for perl 5.19.1:
    HOME=/home/nick
    LANG (unset)
    LANGUAGE=en_US:en
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/home/nick/bin:/opt/local/bin:/opt/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:/usr/local/sbin:/sbin:/usr/sbin
    PERL_BADLANG (unset)
    SHELL=/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Jun 20, 2013

From @nwc10

On Thu, Jun 20, 2013 at 05​:55​:05AM -0700, Nicholas Clark wrote​:

The Perl code in question is this​:

    unless \(@​ready\) \{
        return unless $sel\->count;
        @​ready = $sel\->can\_read;
    \}

    my \( $h\, $parser\, $stash\, @​handles \) = @​\{ shift @​ready \};
    my $result = $parser\->next;

I can see that $count is 6, and @​ready is empty​:

So whose bug is it?

1) pp_sselect, for not restarting on that signal?
2) IO​::Select for returning a contradictory set of results?
3) TAP​::Parser​::Multiplexer, for not coping with this?

I think that the answer is (3), and the correct fix is something like this​:

Inline Patch
diff --git a/cpan/Test-Harness/lib/TAP/Parser/Multiplexer.pm b/cpan/Test-Harness/lib/TAP/Parser/Multiplexer.pm
index 913aa92..a395a77 100644
--- a/cpan/Test-Harness/lib/TAP/Parser/Multiplexer.pm
+++ b/cpan/Test-Harness/lib/TAP/Parser/Multiplexer.pm
@@ -133,7 +133,17 @@ sub _iter {
 
         unless (@ready) {
             return unless $sel->count;
-            @ready = $sel->can_read;
+            # can_read can return an empty list if the select is
+            # interrupted by a signal. In which case restart the select
+            # immediately. There seems little point in trying to sleep
+            # (or similar) before retrying, as all those system calls
+            # would also get interrupted by signals.
+            my $retries;
+            while (!(@ready = $sel->can_read)) {
+                die "select for input was interrupted $retries times ($!). "
+                    . "Something is badly wrong, so aborting"
+                        if ++$retries > 1000;
+            }
         }
 
         my ( $h, $parser, $stash, @handles ) = @{ shift @ready };


Opinions?

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented Jun 20, 2013

From @Leont

On Thu, Jun 20, 2013 at 2​:55 PM, Nicholas Clark
<perlbug-followup@​perl.org> wrote​:

So whose bug is it?

1) pp_sselect, for not restarting on that signal?

That would be the wrong default for all sorts of reasons, including
signal handlers wanting to modify what handles are being watched.

2) IO​::Select for returning a contradictory set of results?

I don't see the contradiction. I do think it fails to indicate errors
in a particularly useful way. It seems it can return an empty array on
time-out (return 0) and on interruption (return -1). This is Bad
Design™.

3) TAP​::Parser​::Multiplexer, for not coping with this?

Yeah, it needs to retry, but arguably only on EINTR.

Leon

@p5pRT
Copy link
Author

p5pRT commented Jun 20, 2013

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

@p5pRT
Copy link
Author

p5pRT commented Jun 20, 2013

From @nwc10

On Thu, Jun 20, 2013 at 05​:16​:07PM +0200, Leon Timmermans wrote​:

On Thu, Jun 20, 2013 at 2​:55 PM, Nicholas Clark
<perlbug-followup@​perl.org> wrote​:

So whose bug is it?

1) pp_sselect, for not restarting on that signal?

That would be the wrong default for all sorts of reasons, including
signal handlers wanting to modify what handles are being watched.

2) IO​::Select for returning a contradictory set of results?

I don't see the contradiction. I do think it fails to indicate errors
in a particularly useful way. It seems it can return an empty array on
time-out (return 0) and on interruption (return -1). This is Bad
Design???.

3) TAP​::Parser​::Multiplexer, for not coping with this?

Yeah, it needs to retry, but arguably only on EINTR.

Leon

On Thu, Jun 20, 2013 at 03​:09​:06PM +0100, Nicholas Clark wrote​:

I think that the answer is (3), and the correct fix is something like this​:

So this would be a better approach?

Inline Patch
diff --git a/cpan/Test-Harness/lib/TAP/Parser/Multiplexer.pm b/cpan/Test-Harness/lib/TAP/Parser/Multiplexer.pm
index 913aa92..bdc21c0 100644
--- a/cpan/Test-Harness/lib/TAP/Parser/Multiplexer.pm
+++ b/cpan/Test-Harness/lib/TAP/Parser/Multiplexer.pm
@@ -133,7 +133,16 @@ sub _iter {
 
         unless (@ready) {
             return unless $sel->count;
-            @ready = $sel->can_read;
+            # can_read can return an empty list if the select is
+            # interrupted by a signal. In which case restart the select
+            # immediately. There seems little point in trying to sleep
+            # (or similar) before retrying, as all those system calls
+            # would also get interrupted by signals.
+            my $retries;
+            while (!(@ready = $sel->can_read)) {
+                die "select for TAP input failed: $!"
+                    unless $!{EINTR};
+            }
         }
 
         my ( $h, $parser, $stash, @handles ) = @{ shift @ready };

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented Jun 20, 2013

From @Leont

On Thu, Jun 20, 2013 at 5​:49 PM, Nicholas Clark <nick@​ccl4.org> wrote​:

On Thu, Jun 20, 2013 at 03​:09​:06PM +0100, Nicholas Clark wrote​:

I think that the answer is (3), and the correct fix is something like this​:

So this would be a better approach?

diff --git a/cpan/Test-Harness/lib/TAP/Parser/Multiplexer.pm b/cpan/Test-Harness/lib/TAP/Parser/Multiplexer.pm
index 913aa92..bdc21c0 100644
--- a/cpan/Test-Harness/lib/TAP/Parser/Multiplexer.pm
+++ b/cpan/Test-Harness/lib/TAP/Parser/Multiplexer.pm
@​@​ -133,7 +133,16 @​@​ sub _iter {

     unless \(@&#8203;ready\) \{
         return unless $sel\->count;

- @​ready = $sel->can_read;
+ # can_read can return an empty list if the select is
+ # interrupted by a signal. In which case restart the select
+ # immediately. There seems little point in trying to sleep
+ # (or similar) before retrying, as all those system calls
+ # would also get interrupted by signals.
+ my $retries;
+ while (!(@​ready = $sel->can_read)) {
+ die "select for TAP input failed​: $!"
+ unless $!{EINTR};
+ }
}

     my \( $h\, $parser\, $stash\, @&#8203;handles \) = @&#8203;\{ shift @&#8203;ready \};

Nicholas Clark

Yeah, that should work in this case (though as already pointed out on
IRC by others $retries is superfluous).

If we had to deal with timeouts too, you'd have to set $! to 0 before
calling can_read. Actually, it may make sense to do that in can_read
itself, since $! is the only way it can signal errors. This situation
does kind of suck :-/.

Leon

@p5pRT
Copy link
Author

p5pRT commented Jun 21, 2013

From @ap

* Nicholas Clark <nick@​ccl4.org> [2013-06-20 17​:50]​:

diff --git a/cpan/Test-Harness/lib/TAP/Parser/Multiplexer.pm b/cpan/Test-Harness/lib/TAP/Parser/Multiplexer.pm
index 913aa92..bdc21c0 100644
--- a/cpan/Test-Harness/lib/TAP/Parser/Multiplexer.pm
+++ b/cpan/Test-Harness/lib/TAP/Parser/Multiplexer.pm
@​@​ -133,7 +133,16 @​@​ sub _iter {

     unless \(@&#8203;ready\) \{
         return unless $sel\->count;

- @​ready = $sel->can_read;
+ # can_read can return an empty list if the select is
+ # interrupted by a signal. In which case restart the select
+ # immediately. There seems little point in trying to sleep
+ # (or similar) before retrying, as all those system calls
+ # would also get interrupted by signals.
+ my $retries;
+ while (!(@​ready = $sel->can_read)) {
+ die "select for TAP input failed​: $!"
+ unless $!{EINTR};
+ }
}

     my \( $h\, $parser\, $stash\, @&#8203;handles \) = @&#8203;\{ shift @&#8203;ready \};

Maybe like so?

  unless (@​ready) {
  return unless $sel->count;
  {
  @​ready = $sel->can_read;
  last if @​ready;
  redo if $!{EINTR}; # got nothing because can_read was
  # interrupted by a signal; restart
  die "select for TAP input failed​: $!";
  }
  }

To my mind that breaks down the steps of the logic better. All the
statements and expressions are much simpler, representing an isolated
decision point each, and the can_read line is not repeated.

I’m not sure your comment regarding `sleep` is even right – it seems to
me that while such a `sleep` would be superfluous, that’s because by the
time the code gets to detect the EINTR condition, a couple of context
switches have already gone by, and there’s nothing left to wait to pass.

--
*AUTOLOAD=*_;sub _{s/​::([^​:]*)$/print$1,(",$\/"," ")[defined wantarray]/e;chop;$_}
&Just->another->Perl->hack;
#Aristotle Pagaltzis // <http​://plasmasturm.org/>

@p5pRT
Copy link
Author

p5pRT commented Jun 21, 2013

From @nwc10

On Fri, Jun 21, 2013 at 03​:00​:46AM +0200, Aristotle Pagaltzis wrote​:

* Nicholas Clark <nick@​ccl4.org> [2013-06-20 17​:50]​:

diff --git a/cpan/Test-Harness/lib/TAP/Parser/Multiplexer.pm b/cpan/Test-Harness/lib/TAP/Parser/Multiplexer.pm
index 913aa92..bdc21c0 100644
--- a/cpan/Test-Harness/lib/TAP/Parser/Multiplexer.pm
+++ b/cpan/Test-Harness/lib/TAP/Parser/Multiplexer.pm
@​@​ -133,7 +133,16 @​@​ sub _iter {

     unless \(@&#8203;ready\) \{
         return unless $sel\->count;

- @​ready = $sel->can_read;
+ # can_read can return an empty list if the select is
+ # interrupted by a signal. In which case restart the select
+ # immediately. There seems little point in trying to sleep
+ # (or similar) before retrying, as all those system calls
+ # would also get interrupted by signals.
+ my $retries;
+ while (!(@​ready = $sel->can_read)) {
+ die "select for TAP input failed​: $!"
+ unless $!{EINTR};
+ }
}

     my \( $h\, $parser\, $stash\, @&#8203;handles \) = @&#8203;\{ shift @&#8203;ready \};

Maybe like so?

unless \(@&#8203;ready\) \{
    return unless $sel\->count;
    \{
        @&#8203;ready = $sel\->can\_read;
        last if @&#8203;ready;
        redo if $\!\{EINTR\}; \# got nothing because can\_read was
                           \# interrupted by a signal; restart
        die "select for TAP input failed&#8203;: $\!";
    \}
\}

Well, apart from the fact that as-is there's no loop for `last` or `redo` :-)

Presumably the inner { } should be a while (1) loop?

To my mind that breaks down the steps of the logic better. All the
statements and expressions are much simpler, representing an isolated
decision point each, and the can_read line is not repeated.

Yes. Others had pointed out tat the my $retries; should be removed. But I
don't think that anyone observed that with it gone, the ->can_read
duplication can go.

But I think that your layout is the thing that I was searching for, but
was elluding me.

I'm not sure your comment regarding `sleep` is even right ' it seems to
me that while such a `sleep` would be superfluous, that's because by the
time the code gets to detect the EINTR condition, a couple of context
switches have already gone by, and there's nothing left to wait to pass.

I was more thinking of things like retrying `fork`, or anything that would
be best done with some kind of backoff, instead of a busy loop.

So yes, I guess my question is "is it obvious that it's not going to be a
problem to have a 'tight' loop for the retry?" As it's not obvious that it's
not obvious, I think that some sort of comment is worthwhile.

Nicholas Clark

@p5pRT
Copy link
Author

p5pRT commented Jun 21, 2013

From @ap

Hi Nick,

* Nicholas Clark <nick@​ccl4.org> [2013-06-21 11​:20]​:

On Fri, Jun 21, 2013 at 03​:00​:46AM +0200, Aristotle Pagaltzis wrote​:

Maybe like so?

unless \(@&#8203;ready\) \{
    return unless $sel\->count;
    \{
        @&#8203;ready = $sel\->can\_read;
        last if @&#8203;ready;
        redo if $\!\{EINTR\}; \# got nothing because can\_read was
                           \# interrupted by a signal; restart
        die "select for TAP input failed&#8203;: $\!";
    \}
\}

Well, apart from the fact that as-is there's no loop for `last` or
`redo` :-)

Presumably the inner { } should be a while (1) loop?

hmm.

I used the naked block on purpose here as I do not see this as a loop
by intent – nor will it be one in practice, outside of somewhat unusual
circumstances (namely `can_read` getting interrupted repeatedly), as
evidenced by the fact that it *mostly* works without proper resuming,
which means it usually doesn’t get interrupted even once.

So I see this as straight-line logic in which `redo` is interspersed as
a form of readable goto to express some exceptional control flow.

Thus my choice to write it this particular way. But I concede that I may
be being too subtle, and that in the interest of obviousness it should
perhaps be written otherwise.

I'm not sure your comment regarding `sleep` is even right ' it seems
to me that while such a `sleep` would be superfluous, that's because
by the time the code gets to detect the EINTR condition, a couple of
context switches have already gone by, and there's nothing left to
wait to pass.

I was more thinking of things like retrying `fork`, or anything that
would be best done with some kind of backoff, instead of a busy loop.

Well, that makes sense for those kinds of things. :-) Your initial cut
was based on number of retries, so back-off was a plausible concern to
consider. But when checking for EINTR, it makes no sense.

So yes, I guess my question is "is it obvious that it's not going to
be a problem to have a 'tight' loop for the retry?" As it's not
obvious that it's not obvious, I think that some sort of comment is
worthwhile.

My understanding is that “EINTR” should inherently suggest “tight loop”,
and that is how I read it, so I opted for as little comment as possible.

But I can’t say how obvious this needs to be made for others.

Regards,
--
Aristotle Pagaltzis // <http​://plasmasturm.org/>

@p5pRT
Copy link
Author

p5pRT commented Jun 21, 2013

From @druud62

On 21/06/2013 03​:00, Aristotle Pagaltzis wrote​:

 unless \(@&#8203;ready\) \{
     return unless $sel\->count;
     \{
         @&#8203;ready = $sel\->can\_read;
         last if @&#8203;ready;
         redo if $\!\{EINTR\}; \# got nothing because can\_read was
                            \# interrupted by a signal; restart
         die "select for TAP input failed&#8203;: $\!";
     \}
 \}

Or like​:

  unless (@​ready) {
  return if !$sel->count;
  until ( @​ready = $sel->can_read ) {
  $!{EINTR} # can_read was interrupted by a signal
  or die "select for TAP input failed​: ", $!;
  }
  }

--
Ruud

@p5pRT
Copy link
Author

p5pRT commented Jun 21, 2013

From @Leont

On Fri, Jun 21, 2013 at 11​:17 AM, Nicholas Clark <nick@​ccl4.org> wrote​:

Well, apart from the fact that as-is there's no loop for `last` or `redo` :-)

I'm not sure your comment regarding `sleep` is even right ' it seems to
me that while such a `sleep` would be superfluous, that's because by the
time the code gets to detect the EINTR condition, a couple of context
switches have already gone by, and there's nothing left to wait to pass.

I was more thinking of things like retrying `fork`, or anything that would
be best done with some kind of backoff, instead of a busy loop.

So yes, I guess my question is "is it obvious that it's not going to be a
problem to have a 'tight' loop for the retry?" As it's not obvious that it's
not obvious, I think that some sort of comment is worthwhile.

In retrying fork it might make sense, but in this case I'd say it only
adds confusion.

Leon

@p5pRT
Copy link
Author

p5pRT commented Jun 21, 2013

From @ap

* Dr.Ruud <rvtol+usenet@​isolution.nl> [2013-06-21 14​:10]​:

Or like​:

unless \(@&#8203;ready\) \{
    return if \!$sel\->count;
    until \( @&#8203;ready = $sel\->can\_read \) \{
        $\!\{EINTR\}  \# can\_read was interrupted by a signal
          or die "select for TAP input failed&#8203;: "\, $\!;
    \}
\}

Yes, that’s the obvious first transformation of Nick’s original code.
I wasn’t satisfied with it, so I went on to rearrange it further to get
what I posted. This form is more compact and has the same effect as far
as the computer cares, but I didn’t find it skimmable enough or explicit
enough in conveying intent to another programmer.

Regards,
--
Aristotle Pagaltzis // <http​://plasmasturm.org/>

@p5pRT
Copy link
Author

p5pRT commented Jun 21, 2013

From @tamias

On Fri, Jun 21, 2013 at 10​:17​:23AM +0100, Nicholas Clark wrote​:

On Fri, Jun 21, 2013 at 03​:00​:46AM +0200, Aristotle Pagaltzis wrote​:

Maybe like so?

unless \(@&#8203;ready\) \{
    return unless $sel\->count;
    \{
        @&#8203;ready = $sel\->can\_read;
        last if @&#8203;ready;
        redo if $\!\{EINTR\}; \# got nothing because can\_read was
                           \# interrupted by a signal; restart
        die "select for TAP input failed&#8203;: $\!";
    \}
\}

Well, apart from the fact that as-is there's no loop for `last` or `redo` :-)

Presumably the inner { } should be a while (1) loop?

The loop control statements work with a bare block.

  Basic BLOCKs

  A BLOCK by itself (labeled or not) is semantically equivalent to a
  loop that executes once. Thus you can use any of the loop control
  statements in it to leave or restart the block. (Note that this is
  NOT true in "eval{}", "sub{}", or contrary to popular belief "do{}"
  blocks, which do NOT count as loops.) The "continue" block is
  optional.

Ronald

@toddr
Copy link
Member

toddr commented Feb 5, 2020

@Leont is this still a bug or was it sorted somewhere in the past. Either way it should be opened over here, right? https://rt.cpan.org/Dist/Display.html?Name=Test-Harness

@Leont
Copy link
Contributor

Leont commented Feb 5, 2020

@Leont is this still a bug or was it sorted somewhere in the past. Either way it should be opened over here, right? https://rt.cpan.org/Dist/Display.html?Name=Test-Harness

Yeah it's still a bug. Reporting here on github is fine, I should probably move that queue anyway.

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

4 participants