EV-cares
view release on metacpan or search on metacpan
eg/cli.pl
eg/dane.pl
eg/dns_compare.pl
eg/dns_proxy.pl
eg/dns_types.pl
eg/dnssec_chain.pl
eg/email_health.pl
eg/futures.pl
eg/healthcheck.pl
eg/healthmon.pl
eg/keep_alive.pl
eg/mta_probe.pl
eg/parallel.pl
eg/resolve.pl
eg/resolver_pool.pl
eg/reverse.pl
eg/spf.pl
eg/spf_chain.pl
eg/srv.pl
eg/svcb.pl
eg/timing.pl
typedef struct {
ev_io watcher;
ares_socket_t fd;
} ev_cares_io_t;
struct ev_cares_s {
U32 magic;
ares_channel channel;
struct ev_loop *loop;
SV *loop_sv; /* keeps a custom EV::Loop alive; NULL for default loop */
ev_timer timer;
ev_cares_io_t ios[MAX_IO];
int active_queries;
int destroyed;
int in_callback; /* prevent Safefree while callbacks run */
int free_pending; /* deferred Safefree after last callback */
int cleanup_pending; /* deferred channel teardown after last callback */
int last_timeouts; /* timeouts count from the most recent callback */
};
}
#endif
else {
warn("EV::cares::new: unknown option '%s'", key);
}
}
Newxz(self, 1, ev_cares_t);
self->magic = EV_CARES_MAGIC;
self->loop = loop_ptr;
/* Keep the EV::Loop's blessed object alive â its DESTROY calls
ev_loop_destroy(). Holding the outer RV is not enough; inc the
underlying SV (the IV that stores the loop pointer). */
if (loop_sv) self->loop_sv = SvREFCNT_inc_simple_NN(SvRV(loop_sv));
for (i = 0; i < MAX_IO; i++)
self->ios[i].fd = ARES_SOCKET_BAD;
opts.sock_state_cb = sock_state_cb;
opts.sock_state_cb_data = self;
optmask |= ARES_OPT_SOCK_STATE_CB;
eg/keep_alive.pl view on Meta::CPAN
#!/usr/bin/env perl
# Long-running daemon pattern: a single EV::cares instance refreshes a
# fixed set of names every $interval seconds, handling transient upstream
# failures by calling reinit() (which re-reads /etc/resolv.conf) and
# logging fail-over behavior. Intended as a copyable starting point for
# health-check daemons that need cached, periodically-refreshed records.
#
# Usage:
# perl eg/keep_alive.pl # default 30s, defaults to a few hosts
# perl eg/keep_alive.pl 5 cloudflare.com github.com
# ^C to stop
use strict;
use warnings;
use EV;
use EV::cares qw(:all);
my $interval = (@ARGV && $ARGV[0] =~ /^\d+\z/) ? shift : 30;
my @names = @ARGV ? @ARGV : qw(cloudflare.com github.com perl.org);
my %TRANSIENT = map { $_ => 1 }
eg/upstream_ad_check.pl view on Meta::CPAN
# Need the EDNS flag so the upstream actually sets DO and reports AD;
# without it many resolvers strip the AD bit out of paranoia.
my $flags = ARES_FLAG_EDNS;
printf "Querying %s for an A record on %d resolver(s)\n\n", $name, scalar @servers;
printf "%-20s %-7s %-7s %-7s %s\n", 'server', 'rcode', 'ad', 'ra', 'note';
printf "%s\n", '-' x 60;
my $pending = scalar @servers;
my @resolvers; # keep resolvers alive across the for loop iterations;
# otherwise each $r drops to refcount 0 at end-of-iter,
# DESTROY runs ares_destroy, and every callback fires
# with ARES_EDESTRUCTION before we ever pump EV::run.
for my $srv (@servers) {
my $r = EV::cares->new(servers => [$srv], flags => $flags, timeout => 5);
push @resolvers, $r;
$r->query($name, C_IN, T_A, sub {
my ($status, $buf) = @_;
my $note = '';
my ($rcode, $ad, $ra) = ('-', '-', '-');
t/06_loop.t view on Meta::CPAN
# resolver retains the loop SV: dropping the user's last ref must not
# free the loop until the resolver itself is gone
{
my $loop = EV::Loop->new;
my $weak = $loop;
weaken($weak);
my $r = EV::cares->new(loop => $loop, lookups => 'f');
undef $loop;
ok(defined $weak, 'loop SV retained while resolver is alive');
undef $r;
ok(!defined $weak, 'loop SV released after resolver destroyed');
}
done_testing;
t/14_concurrent.t view on Meta::CPAN
my $count = 0;
for my $r (@resolvers) {
$r->resolve('localhost', sub { $count++ });
}
my $t2 = EV::timer 5, 0, sub { EV::break };
EV::run until $count >= 5;
is($count, 5, '5 concurrent resolvers each got their callback');
is($_->active_queries, 0, 'each instance settles to 0') for @resolvers;
}
# Independent destroy: destroying one resolver leaves others alive
{
my $live = EV::cares->new(lookups => 'f');
my $doomed = EV::cares->new(lookups => 'f');
$doomed->destroy;
is($doomed->is_destroyed, 1, 'doomed is destroyed');
is($live->is_destroyed, 0, 'live is unaffected');
my $done;
$live->resolve('localhost', sub { $done = 1 });
my $t3 = EV::timer 5, 0, sub { $done = 1 };
( run in 0.830 second using v1.01-cache-2.11-cpan-483215c6ad5 )