Skip Menu |

This queue is for tickets about the Future-AsyncAwait CPAN distribution.

Report information
The Basics
Id: 123062
Status: resolved
Priority: 0/
Queue: Future-AsyncAwait

People
Owner: Nobody in particular
Requestors: tynovsky [...] avast.com
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: 0.16



Subject: AsyncAwait and LibXML
Date: Sun, 17 Sep 2017 09:10:53 +0200
To: bug-Future-AsyncAwait [...] rt.cpan.org
From: "Týnovský, Miroslav" <tynovsky [...] avast.com>
Hi, First of all, thanks for all the great work. I discovered a strange (buggy) behaviour when using Future::AsyncAwait together with XML::LibXML. Particularly, my program exits with error code 0 in the middle of execution. I'm using: Future::AsyncAwait 0.10 XML::LibXML 2.0128 perl v5.24.0 Steps to reproduce: 1. Run the following program #!/usr/bin/env perl use strict; use warnings; use XML::LibXML; use IO::Async::Timer::Periodic; use IO::Async::Loop; use Future::AsyncAwait; use Test::More; my @futures; my $loop = IO::Async::Loop->new; run(); my $timer = IO::Async::Timer::Periodic->new( interval => 1, on_tick => sub { while (my $f = shift @futures) { $f->done(1) } }, ); $loop->add($timer); $timer->start(); $loop->run(); async sub run { await f1(); print "f1\n"; await f2(); print "f2\n"; $loop->stop(); pass(); done_testing(); } async sub f1 { await new_future(); my $return = 1; return $return } sub f2 { return new_future(); } sub new_future { # XML::LibXML->load_xml(string => '<a />'); my $f = $loop->new_future(); push @futures, $f; return $f } You should see the following output: f1 f2 ok 1 1..1 2. Now uncomment the line which is commented out XML::LibXML->load_xml(string => '<a />'); and execute again. Now the output is incomplete - part of the program didn't get executed: f1 And the program still exited with exitcode 0. 3. Execute again with environment PERL_FUTURE_DEBUG=1 set. It works properly again. 4. Also note that f1 needs to contain await in order to reproduce the bug. I have no guess about the cause. Let me know if I can provide any more details you potentially need. Thank you, Miroslav
It's not only XML::LibXML. Another line which breaks the program is HTTP::Tiny->get('http://www.metacpan.org'); I suspect there will be many others. I keep trying to find the simplest case.
On Sun Sep 17 03:11:45 2017, tynovsky@avast.com wrote: Show quoted text
> You should see the following output: > > f1 > f2 > ok 1 > 1..1
Mine stops at f1 even unmodified. However, I see a potential reason here. Line 15 calls simply run(); without storing the returned Future anywhere. That's not going to go well. Saving it as my $f = run(); doesn't appear to help though. This program does seem a little confused though, as it's managing the IO::Async loop using ->run as well as working with toplevel Futures. I wonder if that's related. In any case this is all before I uncomment the line about XML::LibXML so I don't think that's related. -- Paul Evans
I now have a rather smaller test case - see attached -- Paul Evans
Subject: rt123062.pl
#!/usr/bin/env perl use strict; use warnings; use Future::AsyncAwait; use IO::Async::Loop; use IO::Async::Timer::Periodic; my $loop = IO::Async::Loop->new; my @futures; $loop->add( IO::Async::Timer::Periodic->new( interval => 1, on_tick => sub { while (my $f = shift @futures) { $f->done(1) } }, )->start ); run()->get; async sub run { await new_future(); print "f1\n"; await f2(); print "f2\n"; } async sub f1 { await new_future(); } sub f2 { return new_future(); } sub new_future { my $f = $loop->new_future(); push @futures, $f; return $f }
On Thu Jan 18 21:58:58 2018, PEVANS wrote: Show quoted text
> I now have a rather smaller test case - see attached
Curiously, this test case fails alone but passes with PERL_FUTURE_DEBUG=1: $ perl rt123062.pl f1 $ PERL_FUTURE_DEBUG=1 perl rt123062.pl f1 f2 It also passes if you change line 26: - await f1(); + await new_future(); Clearly something quite subtle going on here -- Paul Evans
Well now this is just getting stranger. By adding an END { print "END\n"; } to the program, it prints in both cases, thus showing it to be a fairly controlled termination by perl, and not say a silent variation of a SEGV. Also the exit code is zero in both cases. By careful division down of the various effects of PERL_FUTURE_DEBUG I have narrowed it down to a single line in Future.pm: 376 $self->{ready_at} = _shortmess $_[0] if DEBUG; by making that line unconditionally execute, the test program now always passes. It seems that this line has the odd side-effect of causing it not to exit prematurely. -- Paul Evans
Almost certainly somehow related to https://rt.cpan.org/Ticket/Display.html?id=126037 -- Paul Evans
On Thu Jan 03 10:28:22 2019, PEVANS wrote: Show quoted text
> Almost certainly somehow related to > > https://rt.cpan.org/Ticket/Display.html?id=126037
Yup. It was. With RT126037 fixed, this one is now working too: leo@shy:~/src/perl/Future-AsyncAwait [bzr] $ perl -Mblib rt123062.pl ENTER get() f1 ENTER f2() f2 EOF END leo@shy:~/src/perl/Future-AsyncAwait [bzr] $ PERL_FUTURE_DEBUG=1 perl -Mblib rt123062.pl ENTER get() f1 ENTER f2() f2 EOF END -- Paul Evans
Released in 0.16 -- Paul Evans