Appropiate Coro/AnyEvent model?
Andrew Whatson
whatson at gmail.com
Fri Nov 15 01:14:23 CET 2013
Hi Mark,
You're on the right track, but it sounds like you're only waiting for
success inside do_stuff(), but because success never happens, it gets
stuck waiting forever. Seems that really you should be waiting for
success OR error, and have some way to tell the difference. Here's
one approach:
sub new {
...
$self->{err_watcher} = AE::io $self->{child_stderr}, 0, sub {
$self->{got_error} = 1;
$self->{interrupt}->() if $self->{interrupt};
};
$self->{child_watcher} = AE::child $self->{child_pid}, sub {
$self->{got_exit} = 1;
$self->{interrupt}->() if $self->{interrupt};
};
}
sub do_stuff {
...
$self->{interrupt} = rouse_cb;
AE::io $self->{child_stdout}, 0, $self->{interrupt};
rouse_wait $self->{interrupt};
$self->{interrupt} = undef;
if ($self->{got_error}) {
...
}
elsif ($self->{got_exit}) {
...
}
else {
...
}
}
Regards,
Andrew Whatson
On 15 November 2013 08:47, Mark Lawrence <nomad at null.net> wrote:
> I'm struggling with the right way of combining Coro for blocking-style
> code, with AnyEvent for handling event-triggered error conditions.
>
> I am writing a client application which forks off a child process to
> communicate with, for which I would like:
>
> 1. Errors due to the fork/exec or on stderr file handle reads to
> terminate the coroutine/program, cleanly.
>
> 2. The main protocol parts to run sequentially
> (using rouse_cb/rouse_wait)
>
> The symptoms I'm seeing while trying to make this work are usually
> something that results in the program busy-waiting in a loop.
>
> Here is what I've come up with so far:
>
> package Client;
> use AnyEvent::Handle;
>
> sub new {
>
> # dup + fork + exec, saving stdin, stdout and stderr of child
>
> $self->{err_watcher} = AnyEvent::Handle->new(
> fh => $stderr,
> on_read => sub {
>
> # How to cancel the below async from here? Coro::terminate
> # seems to infinite loop
>
> },
> );
>
> $self->{child_watcher} = AnyEvent->child(
> pid => ...,
> cb => sub {
>
> # Same question here. If the child fails early for some
> # reason how to cancel async from here?
> },
> );
> }
>
> sub do_stuff {
>
> # Here I use rouse_cb and rouse_wait on $stdin, and if the
> # communication with the server is successful, returning from
> # here should naturally terminate the async block below
> }
>
>
> package main;
> use Coro;
>
> my $coro = async {
> my $client = Client->new;
> $client->do_stuff;
> };
>
> $coro->join;
>
> I have spent hours and hours looking over the documentation for Coro
> and AnyEvent, and there are many examples, but none that speak clearly
> to me about how to set this up correctly. terminate() seems to
> sometimes hang, cancel() is a bit of hammer but also sometimes hangs,
> and throw() kills everything. I suspect I've just got the model wrong.
> Would appreciate some advice.
>
> --
> Mark Lawrence
>
> _______________________________________________
> anyevent mailing list
> anyevent at lists.schmorp.de
> http://lists.schmorp.de/mailman/listinfo/anyevent
More information about the anyevent
mailing list