Skip Menu |

This queue is for tickets about the Net-DNS CPAN distribution.

Report information
The Basics
Id: 121897
Status: resolved
Priority: 0/
Queue: Net-DNS

People
Owner: Nobody in particular
Requestors: felipe [...] felipegasper.com
Cc:
AdminCc:

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



Subject: REQUEST: Make bgbusy() timeout adjustable?
Date: Thu, 25 May 2017 15:55:12 -0400
To: bug-Net-DNS [...] rt.cpan.org
From: Felipe Gasper <felipe [...] felipegasper.com>
Hello, It would be useful to be able to specify a custom timeout for bgbusy(); could this be added as a 2nd parameter to that function? Thank you! -FG
Index: lib/Net/DNS/Resolver/Base.pm =================================================================== --- lib/Net/DNS/Resolver/Base.pm (revision 1567) +++ lib/Net/DNS/Resolver/Base.pm (working copy) @@ -617,7 +617,7 @@ sub bgbusy { - my ( $self, $handle ) = @_; + my ( $self, $handle, $timeout ) = @_; return unless $handle; my $appendix = ${*$handle}{net_dns_bg} ||= [time() + $self->{udp_timeout}]; @@ -624,7 +624,11 @@ my ( $expire, $query, $read ) = @$appendix; return if ref($read); - unless ( IO::Select->new($handle)->can_read(0.2) ) { + if (!defined $timeout) { + $timeout = 0.2; + } + + unless ( IO::Select->new($handle)->can_read($timeout) ) { return time() <= $expire; } Index: lib/Net/DNS/Resolver.pm =================================================================== --- lib/Net/DNS/Resolver.pm (revision 1567) +++ lib/Net/DNS/Resolver.pm (working copy) @@ -383,7 +383,7 @@ $handle = $resolver->bgsend( 'foo.example.com' ); - while ($resolver->bgbusy($handle)) { + while ($resolver->bgbusy($handle, $optional_timeout)) { ... } @@ -392,6 +392,9 @@ Returns true while awaiting the response or for the transaction to time out. The argument is the handle returned by C<bgsend>. +<$optional_timeout> gives the timeout length in seconds. +Its default value is 0.2. + Truncated UDP packets will be retried over TCP transparently while continuing to assert busy to the caller.
From: rwfranks [...] acm.org
On Thu May 25 16:25:42 2017, felipe@felipegasper.com wrote: Show quoted text
> Hello, > > It would be useful to be able to specify a custom timeout for > bgbusy(); could this be added as a 2nd parameter to that function? >
The timeouts are already configurable in the resolver. $resolver = new Net::DNS::Resolver( udp_timeout => 10, tcp_timeout => 10 ); $resolver->bgbusy() is a Boolean function provided for the user script to determine when the timeout interval has expired. The 0.2 in the can_read() is intended to limit the polling rate and must not be changed by end users.
Subject: Re: [rt.cpan.org #121897] REQUEST: Make bgbusy() timeout adjustable?
Date: Tue, 30 May 2017 15:18:54 -0400
To: bug-Net-DNS [...] rt.cpan.org
From: Felipe Gasper <felipe [...] felipegasper.com>
Show quoted text
> On 30 May 2017, at 3:15 PM, Dick Franks via RT <bug-Net-DNS@rt.cpan.org> wrote: > > <URL: https://rt.cpan.org/Ticket/Display.html?id=121897 > > > On Thu May 25 16:25:42 2017, felipe@felipegasper.com wrote:
>> Hello, >> >> It would be useful to be able to specify a custom timeout for >> bgbusy(); could this be added as a 2nd parameter to that function? >>
> > The timeouts are already configurable in the resolver. > > $resolver = new Net::DNS::Resolver( udp_timeout => 10, tcp_timeout => 10 ); > > $resolver->bgbusy() is a Boolean function provided for the user script to determine when the timeout interval has expired. > > The 0.2 in the can_read() is intended to limit the polling rate and must not be changed by end users. >
It should be the application that decides on limits on polling rates. Making the application wait 200ms merely to check to see if there’s been a response seems pretty awkward for performance-sensitive contexts. For that matter, it would be nice if there were a bgselect() method or some such mechanism to wait on multiple handles concurrently. (They’re just sockets, of course, so select() works just fine, except the docs forbid callers to do that, so.) -F
From: rwfranks [...] acm.org
On Tue May 30 15:19:07 2017, felipe@felipegasper.com wrote: Show quoted text
> > It should be the application that decides on limits on polling rates. > Making the application wait 200ms merely to check to see if there’s > been a response seems pretty awkward for performance-sensitive > contexts.
You misunderstand how this works. The 200ms is the maximum time the IO::Select will wait for a reply before traversing the external loop. If the external loop is empty the wait will be restarted immediately. bgbusy() returns false as soon as the reply packet arrives. Show quoted text
> For that matter, it would be nice if there were a bgselect() method or > some such mechanism to wait on multiple handles concurrently
This is not a general purpose socket library, merely a simple mechanism for actioning background queries. Show quoted text
> (They’re just sockets, of course, so select() works just fine, except the docs > forbid callers to do that, so.)
They are NOT just sockets, they just look like sockets but have other information hidden inside.
Subject: Re: [rt.cpan.org #121897] REQUEST: Make bgbusy() timeout adjustable?
Date: Tue, 30 May 2017 18:24:46 -0400
To: bug-Net-DNS [...] rt.cpan.org
From: Felipe Gasper <felipe [...] felipegasper.com>
Show quoted text
> On 30 May 2017, at 6:15 PM, Dick Franks via RT <bug-Net-DNS@rt.cpan.org> wrote: > > <URL: https://rt.cpan.org/Ticket/Display.html?id=121897 > > > On Tue May 30 15:19:07 2017, felipe@felipegasper.com wrote:
>> >> It should be the application that decides on limits on polling rates. >> Making the application wait 200ms merely to check to see if there’s >> been a response seems pretty awkward for performance-sensitive >> contexts.
> > You misunderstand how this works. > > The 200ms is the maximum time the IO::Select will wait for a reply before traversing the external loop. If the external loop is empty the wait will be restarted immediately. bgbusy() returns false as soon as the reply packet arrives.
… but it will wait up to 200ms until then. So, if the DNS server doesn’t respond, or the UDP packet gets lost, the application freezes for that length. This should be controllable by the application; for example, if the application doesn’t want to wait at all but merely wants to check, 0 could be passed in. Then the application could go off and do other things and check back in later. Right now Net::DNS “punishes” the application merely for asking whether there’s a response yet. Show quoted text
> >
>> For that matter, it would be nice if there were a bgselect() method or >> some such mechanism to wait on multiple handles concurrently
> > This is not a general purpose socket library, merely a simple mechanism for actioning background queries. >
But it only allows checking one background query at a time. bgselect() would allow checking multiple queries concurrently. Show quoted text
>
>> (They’re just sockets, of course, so select() works just fine, except the docs >> forbid callers to do that, so.)
> > They are NOT just sockets, they just look like sockets but have other information hidden inside. >
Sorry … they’re “at least” sockets. :) select() works on them, anyhow; unfortunately, that’s the only way right now to use them with this degree of flexibility. -FG
From: rwfranks [...] acm.org
On Tue May 30 18:25:18 2017, felipe@felipegasper.com wrote: Show quoted text
> Right now Net::DNS “punishes” the application merely for asking > whether there’s a response yet.
The original reason for rate-limiting bgbusy() loops was to avoid uselessly burning lots of CPU time creating and tearing down IO::Select objects in a tight loop. There is such a tight loop in bgread(), allowing a user to avoid coding his own wait loop. I assume you are really arguing for a zero dwell time on the IO::Select rather than a wish to specify an arbitrary value. Show quoted text
> But it only allows checking one background query at a time. bgselect() > would allow checking multiple queries concurrently.
Sure, but it does not fit easily into the Net::DNS model as presently realised. Show quoted text
> >> (They’re just sockets, of course, so select() works just fine, > >> except the docs > >> forbid callers to do that, so.)
> > > > They are NOT just sockets, they just look like sockets but have other > > information hidden inside. > >
> > Sorry … they’re “at least” sockets. :) select() works on them, anyhow; > unfortunately, that’s the only way right now to use them with this > degree of flexibility.
These "sockets" can transform themselves from UDP into TCP if a reply packet is truncated and the query is retried automatically. A Do-It-Yourself select scheme will get very confused when that happens.
Subject: Re: [rt.cpan.org #121897] REQUEST: Make bgbusy() timeout adjustable?
Date: Wed, 31 May 2017 08:42:35 -0400
To: bug-Net-DNS [...] rt.cpan.org
From: Felipe Gasper <felipe [...] felipegasper.com>
Show quoted text
> On 30 May 2017, at 8:14 PM, Dick Franks via RT <bug-Net-DNS@rt.cpan.org> wrote: > > <URL: https://rt.cpan.org/Ticket/Display.html?id=121897 > > > On Tue May 30 18:25:18 2017, felipe@felipegasper.com wrote: >
>> Right now Net::DNS “punishes” the application merely for asking >> whether there’s a response yet.
> > The original reason for rate-limiting bgbusy() loops was to avoid uselessly burning lots of CPU time creating and tearing down IO::Select objects in a tight loop. There is such a tight loop in bgread(), allowing a user to avoid coding his own wait loop.
… assuming that that user wants to make only one N::D::R query at a time. Consider the case of having two concurrent queries. There’s no documented way currently to receive an event when the first of these is available to bgread(). The only way is to roll one’s own select() loop--despite the admonishments in the documentation--and hope for the best. *That* could be solved by accepting multiple handles to bgbusy(), which would seem pretty simple to implement? But, again, without being able to specify a wait time, N::D::R is assuming that the application has nothing better to do than to wait an arbitrary length of time for that event. There’s another issue: N::D::R creates an extra IO::Select and select() system call on every bgread(). So if I do: 1 while $resolver->bgbusy($handle); $packet = $resolver->bgread($handle); … that’s actually doing at two select()s and creating at least two IO::Select objects. Why use IO::Select in the first place, btw? Are there portability advantages? Those could be cached within the handle to avoid recreating them. Show quoted text
> > I assume you are really arguing for a zero dwell time on the IO::Select rather than a wish to specify an arbitrary value.
I actually hadn’t noticed that bgread() includes a zero-wait select(). That seems to contradict the documentation, which speaks of a timeout? That might be useful to document if it’s intended that people can do bgread() as a zero-wait check on the socket. Anyhow. My team currently implements an 0.05 wait time; neither the code’s original author nor I are sure of the original rationale. Show quoted text
>
>> But it only allows checking one background query at a time. bgselect() >> would allow checking multiple queries concurrently.
> > Sure, but it does not fit easily into the Net::DNS model as presently realised.
Is there a git mirror of the repo that can accept pull requests? I’ve forgotten the svn-fu that used to be my daily grind. :) I’d be willing to take a crack at adding this if you like. Show quoted text
> >
>>>> (They’re just sockets, of course, so select() works just fine, >>>> except the docs >>>> forbid callers to do that, so.)
>>> >>> They are NOT just sockets, they just look like sockets but have other >>> information hidden inside. >>>
>> >> Sorry … they’re “at least” sockets. :) select() works on them, anyhow; >> unfortunately, that’s the only way right now to use them with this >> degree of flexibility.
> > These "sockets" can transform themselves from UDP into TCP if a reply packet is truncated and the query is retried automatically. A Do-It-Yourself select scheme will get very confused when that happens. >
So far we’re safe: we do a manual select(), then bgbusy() on the evented handles, then bgread(). It’s definitely not ideal, but it’s the only way for now, and our application needs a more efficient path than waiting on a single handle at a time. Obviously we’d love to use upstream logic instead. -FG
From: rwfranks [...] acm.org
On Wed May 31 08:42:46 2017, felipe@felipegasper.com wrote: Show quoted text
> … assuming that that user wants to make only one N::D::R query at a > time.
That assumption was baked into Net::DNS long ago. Show quoted text
> Consider the case of having two concurrent queries. There’s no > documented way currently to receive an event when the first of these > is available to bgread(). The only way is to roll one’s own select() > loop--despite the admonishments in the documentation--and hope for the > best. > > *That* could be solved by accepting multiple handles to bgbusy(), > which would seem pretty simple to implement? But, again, without being > able to specify a wait time, N::D::R is assuming that the application > has nothing better to do than to wait an arbitrary length of time for > that event.
Out of scope for the present discussion, but willing to consider better ideas. Show quoted text
> There’s another issue: N::D::R creates an extra IO::Select and > select() system call on every bgread(). So if I do: > > 1 while $resolver->bgbusy($handle); > $packet = $resolver->bgread($handle); > > … that’s actually doing at two select()s and creating at least two > IO::Select objects.
See below Show quoted text
> Why use IO::Select in the first place, btw? Are there portability > advantages?
As I pointed out earlier, there is other information added to the object. Extending IO::Select is easier than writing another package from scratch. Show quoted text
> Those could be cached within the handle to avoid > recreating them.
Tempting, but that creates indirect self-references which prevents memory from being reclaimed. That bring in its wake either DESTROY() methods to disentangle the objects, or using weak references which one needs to be careful not to copy lest they regain their strength. Show quoted text
> > I assume you are really arguing for a zero dwell time on the > > IO::Select rather than a wish to specify an arbitrary value.
You did not answer the question: Would you be happy (happier?) with a zero dwell time in bgbusy(), assuming the tight loop objection can be overcome? Yes or No? Show quoted text
> I actually hadn’t noticed that bgread() includes a zero-wait select(). > That seems to contradict the documentation, which speaks of a timeout? > That might be useful to document if it’s intended that people can do > bgread() as a zero-wait check on the socket.
Forget about select() and zero waits, they are implementation detail. Concentrate on the abstract object model. The (Resolver) documentation is quite clear that if you have a handle from bgsend(), then you can use bgread() to obtain the response. Nowhere does it say that you need to test bgbusy() first. (FYI Older versions did need to test bgisready().) Look more carefully at the code: sub bgread { while (&bgbusy) { next; } # side effect: TCP retry &_bgread; } sub _bgread { my ( $self, $handle ) = @_; return unless $handle; my $appendix = ${*$handle}{net_dns_bg}; my ( $expire, $query, $read ) = @$appendix; return shift(@$read) if ref($read); return unless IO::Select->new($handle)->can_read(0); my $peer = $handle->peerhost; $self->answerfrom($peer); bgread() contains a bgbusy() loop before calling _bgread(), so it is ok to do bgread() straight after bgsend(). The can_read(0) in _bgread() is needed to decide if the bgbusy() loop ended because a packet arrived or the timeout interval expired. Show quoted text
> Anyhow. My team currently implements an 0.05 wait time; neither the > code’s original author nor I are sure of the original rationale.
I guess the author's rationale was much the same as mine, tight busy loops. Just for fun, I removed the 200ms dwell in bgbusy() and measured the speed of the loop running on my laptop. 68000 per second! Show quoted text
> >> But it only allows checking one background query at a time. > >> bgselect() > >> would allow checking multiple queries concurrently.
> > > > Sure, but it does not fit easily into the Net::DNS model as presently > > realised.
> > Is there a git mirror of the repo that can accept pull requests? I’ve > forgotten the svn-fu that used to be my daily grind. :) > > I’d be willing to take a crack at adding this if you like.
Too many users depend on this distro, so uncontrolled code bashing is not really an option. If you want to redesign this bit of the resolver, the way to start is to write some outline documentation with example use-cases. The idea is to capture the abstract object model from the user perspective. Email me directly to discuss further. Show quoted text
> >> Sorry … they’re “at least” sockets. :) select() works on them, > >> anyhow; > >> unfortunately, that’s the only way right now to use them with this > >> degree of flexibility.
> > > > These "sockets" can transform themselves from UDP into TCP if a reply > > packet is truncated and the query is retried automatically. A Do-It- > > Yourself select scheme will get very confused when that happens. > >
> > So far we’re safe: we do a manual select(), then bgbusy() on the > evented handles, then bgread(). It’s definitely not ideal, but it’s > the only way for now, and our application needs a more efficient path > than waiting on a single handle at a time. Obviously we’d love to use > upstream logic instead.
It would be useful for us to know a bit of detail about what your application is trying to do.
Subject: Re: [rt.cpan.org #121897] REQUEST: Make bgbusy() timeout adjustable?
Date: Thu, 1 Jun 2017 11:31:00 -0400
To: bug-Net-DNS [...] rt.cpan.org
From: Felipe Gasper <felipe [...] felipegasper.com>
Show quoted text
> On 31 May 2017, at 8:44 PM, Dick Franks via RT <bug-Net-DNS@rt.cpan.org> wrote: > > <URL: https://rt.cpan.org/Ticket/Display.html?id=121897 > > > On Wed May 31 08:42:46 2017, felipe@felipegasper.com wrote: >
>> … assuming that that user wants to make only one N::D::R query at a >> time.
> > That assumption was baked into Net::DNS long ago.
Is that a fundamental, immovable tenet? It would seem relatively straightforward to accommodate concurrent queries, though the “magic” TCP fallback complicates that. Show quoted text
> >
>> Consider the case of having two concurrent queries. There’s no >> documented way currently to receive an event when the first of these >> is available to bgread(). The only way is to roll one’s own select() >> loop--despite the admonishments in the documentation--and hope for the >> best. >> >> *That* could be solved by accepting multiple handles to bgbusy(), >> which would seem pretty simple to implement? But, again, without being >> able to specify a wait time, N::D::R is assuming that the application >> has nothing better to do than to wait an arbitrary length of time for >> that event.
> > Out of scope for the present discussion, but willing to consider better ideas. >
This is actually probably *more* useful to us than the adjustable timeout, but yes, it’s not the same issue. Show quoted text
>
>> Why use IO::Select in the first place, btw? Are there portability >> advantages?
> > As I pointed out earlier, there is other information added to the object. Extending IO::Select is easier than writing another package from scratch.
Oh, I just meant that a raw select() would be lighter, ISTM without a too-significant maintainability hit. Show quoted text
>
>>> I assume you are really arguing for a zero dwell time on the >>> IO::Select rather than a wish to specify an arbitrary value.
> > You did not answer the question: > > Would you be happy (happier?) with a zero dwell time in bgbusy(), assuming the tight loop objection can be overcome? > > Yes or No? >
It would certainly be an improvement, IMO, though I don’t see the use of allowing zero dwell exclusive of an adjustable dwell. Show quoted text
>
>> I actually hadn’t noticed that bgread() includes a zero-wait select(). >> That seems to contradict the documentation, which speaks of a timeout? >> That might be useful to document if it’s intended that people can do >> bgread() as a zero-wait check on the socket.
> > Forget about select() and zero waits, they are implementation detail. > Concentrate on the abstract object model. > > The (Resolver) documentation is quite clear that if you have a handle from bgsend(), then you can use bgread() to obtain the response. Nowhere does it say that you need to test bgbusy() first. (FYI Older versions did need to test bgisready().)
^^ … which is what I’d expect just going by the normal semantics of non-blocking I/O. IMO the documentation is misleading when it describes the conditions under which undef is returned; to my sense, “no response was received” is a different state from “no response is currently available”.  Show quoted text
> > > The can_read(0) in _bgread() is needed to decide if the bgbusy() loop ended because a packet arrived or the timeout interval expired. >
Off-topic, but: consider making the return of bgbusy() indicate which condition happened? Show quoted text
>
>>>> Sorry … they’re “at least” sockets. :) select() works on them, >>>> anyhow; >>>> unfortunately, that’s the only way right now to use them with this >>>> degree of flexibility.
>>> >>> These "sockets" can transform themselves from UDP into TCP if a reply >>> packet is truncated and the query is retried automatically. A Do-It- >>> Yourself select scheme will get very confused when that happens. >>>
>> >> So far we’re safe: we do a manual select(), then bgbusy() on the >> evented handles, then bgread(). It’s definitely not ideal, but it’s >> the only way for now, and our application needs a more efficient path >> than waiting on a single handle at a time. Obviously we’d love to use >> upstream logic instead.
> > It would be useful for us to know a bit of detail about what your application is trying to do. >
The current operation is: given authoritative NSs 1.2.3.4, 2.3.4.5, and 3.4.5.6 for example.com, we want the A record for that domain as fast as it can be delivered. So we send off concurrent queries to all three NSs and wait for the first response. Incidentally, we just started using Net::DNS::Nameserver for some automated testing, and it works like a charm. Thank you for your time and for maintaining this distribution! -FG
From: rwfranks [...] acm.org
On Thu Jun 01 11:31:16 2017, felipe@felipegasper.com wrote: Show quoted text
>
> > That assumption was baked into Net::DNS long ago.
> > Is that a fundamental, immovable tenet? It would seem relatively > straightforward to accommodate concurrent queries, though the “magic” > TCP fallback complicates that.
There is no problem about concurrent queries. The problem arises from your unreasonable expectation that they might somehow share a single select(), which they do not, and can not. Show quoted text
> Would you be happy (happier?) with a zero dwell time in bgbusy(),
> > assuming the tight loop objection can be overcome? > > > > Yes or No? > >
> > It would certainly be an improvement, IMO, though I don’t see the use > of allowing zero dwell exclusive of an adjustable dwell.
Equally, I fail to see how the dwell time matters at all. Show quoted text
> IMO the documentation is misleading when it describes the conditions > under which undef is returned; to my sense, “no response was received” > is a different state from “no response is currently available”.
bgbusy() asserts true whilst waiting for a response: "busy", or false when it has arrived, or decided it never will: "not busy". Show quoted text
> Off-topic, but: consider making the return of bgbusy() indicate which > condition happened?
bgbusy() is a predicate, i.e. Boolean, function so there is no way it can indicate. Show quoted text
> >> So far we’re safe: we do a manual select(), then bgbusy() on the > >> evented handles, then bgread(). It’s definitely not ideal, but it’s > >> the only way for now, and our application needs a more efficient > >> path > >> than waiting on a single handle at a time. Obviously we’d love to > >> use > >> upstream logic instead.
That is the only way of servicing multiple queries using a single IO::Select That usage is unsupported behaviour, so you must accept responsibility for making it work. The dwell time inside bgbusy() is irrelevant except in the special case of TCP retry of a truncated packet, when you have little choice except to wait for the reply. This is so because the handles that your select() identifies as ready for reading, will be "not busy" and drop straight through bgbusy() with no delay. Show quoted text
> The current operation is: given authoritative NSs 1.2.3.4, 2.3.4.5, > and 3.4.5.6 for example.com, we want the A record for that domain as > fast as it can be delivered. So we send off concurrent queries to all > three NSs and wait for the first response.
I do not propose to tear the resolver to bits to support this very limited example of concurrence. What I will do is use a zero dwell time inside bgbusy() so that it returns immediately.
Subject: Re: [rt.cpan.org #121897] REQUEST: Make bgbusy() timeout adjustable?
Date: Thu, 1 Jun 2017 23:59:53 -0400
To: bug-Net-DNS [...] rt.cpan.org
From: Felipe Gasper <felipe [...] felipegasper.com>
Show quoted text
> On 1 Jun 2017, at 9:33 PM, Dick Franks via RT <bug-Net-DNS@rt.cpan.org> wrote: > > <URL: https://rt.cpan.org/Ticket/Display.html?id=121897 > > > On Thu Jun 01 11:31:16 2017, felipe@felipegasper.com wrote:
>>
>>> That assumption was baked into Net::DNS long ago.
>> >> Is that a fundamental, immovable tenet? It would seem relatively >> straightforward to accommodate concurrent queries, though the “magic” >> TCP fallback complicates that.
> > There is no problem about concurrent queries. > The problem arises from your unreasonable expectation that they might somehow share a single select(), which they do not, and can not.
The igntc() flag would seem to take care of the issue that the TCP auto-fallback presents? Show quoted text
>
>> IMO the documentation is misleading when it describes the conditions >> under which undef is returned; to my sense, “no response was received” >> is a different state from “no response is currently available”.
> > bgbusy() asserts true whilst waiting for a response: "busy", or false when it has arrived, or decided it never will: "not busy".
Sorry; I was talking about bgread(). I suppose it’s not actually inaccurate as written; I just misread it. Show quoted text
> >
>> Off-topic, but: consider making the return of bgbusy() indicate which >> condition happened?
> > bgbusy() is a predicate, i.e. Boolean, function so there is no way it can indicate. >
Clarification: for bgbusy(), yes, but bgisready() could do: 0 - not ready 1 - ready to read 2 - timeout etc. In a green-field context I’d suggest making the timeout an exception, but that would be pretty disruptive. Show quoted text
> > What I will do is use a zero dwell time inside bgbusy() so that it returns immediately. >
Wouldn’t that likely break existing implementations that do: 1 while $dns->bgbusy(); my $packet = $dns->bgread(); ?? Or at least make them select() over and over with no delay? I think my team’s path forward for now is to set igntc() and do the TCP fallback manually. -F
From: rwfranks [...] acm.org
On Fri Jun 02 00:00:17 2017, felipe@felipegasper.com wrote: Show quoted text
> > bgbusy() is a predicate, i.e. Boolean, function so there is no way it > > can indicate. > >
> > Clarification: for bgbusy(), yes, but bgisready() could do: > > 0 - not ready > > 1 - ready to read > > 2 - timeout > > etc.
bgisready() is the logical complement of bgbusy() so it can not. Show quoted text
> In a green-field context I’d suggest making the timeout an exception, > but that would be pretty disruptive.
This is not a green field, we are 20 years down the line, with thousands of users. Show quoted text
> I think my team’s path forward for now is to set igntc() and do the > TCP fallback manually.
Why overcomplicate things. Unless I misunderstood something, and all you are interested in is end-to-end speed, your situation appears to be: The _same_ query get sent to all nameservers, which will all respond in same way, or not at all. As the responses are all the same, the only one that matters is the first to arrive. If the UDP packet is truncated, it can be retried automatically by the bgbusy() inside bgread(). my $resolver = new Net::DNS::Resolver( udp_timeout => 5, tcp_timeout => 20 ); my $query = new Net::DNS::Packet( $name, 'A' ); my $select = new IO::Select(); foreach (@nameserver) { $resolver->nameserver($_); my $handle = bgsend($query); $select->add($handle) } my @done; until ( scalar( @done = $select->canread() ) ) { do something else } my ( $winner, @losers ) = @done; undef $select; # no prizes for the losers my $packet = $resolver->bgread($winner); # TCP retry done transparently
Subject: Re: [rt.cpan.org #121897] REQUEST: Make bgbusy() timeout adjustable?
Date: Sat, 3 Jun 2017 11:43:37 -0400
To: bug-Net-DNS [...] rt.cpan.org
From: Felipe Gasper <felipe [...] felipegasper.com>
Show quoted text
> On 2 Jun 2017, at 10:21 AM, Dick Franks via RT <bug-Net-DNS@rt.cpan.org> wrote: > > <URL: https://rt.cpan.org/Ticket/Display.html?id=121897 > > > On Fri Jun 02 00:00:17 2017, felipe@felipegasper.com wrote: >
>>> bgbusy() is a predicate, i.e. Boolean, function so there is no way it >>> can indicate. >>>
>> >> Clarification: for bgbusy(), yes, but bgisready() could do: >> >> 0 - not ready >> >> 1 - ready to read >> >> 2 - timeout >> >> etc.
> > bgisready() is the logical complement of bgbusy() so it can not. >
bgisready() could easily handle it, and bgbusy() would still be its logical complement. It wouldn’t fit the ideal of deprecating bgisready(), of course, but it would still accord with the status quo documentation. Show quoted text
>
>> I think my team’s path forward for now is to set igntc() and do the >> TCP fallback manually.
> > Why overcomplicate things. >
I’d have to dig to figure out more, but when we used the automatic TCP fallback before an unresponsive DNS server caused our resolver code to hang. The author of our internal code mentioned that, to his recollection, this particular resolver logic is at least half as old as Net::DNS itself, and possibly older. There’s a lot of strange stuff in there--by no means limited to the interaction with Net::DNS. I’ve actually been playing around with a rewrite of our code and am trying it now without the bgisready() as you suggest. Initial testing seems to be fine; we’ll see what comes. Anyhow, thank you for your responses. -FG
From: rwfranks [...] acm.org
On Sat Jun 03 11:43:47 2017, felipe@felipegasper.com wrote: Show quoted text
> bgisready() could easily handle it, and bgbusy() would still be its > logical complement.
Nonsense! bgisready() is also a predicate. bgisready(x) is defined as not(bgbusy(x)) and is provided for backward compatibility. Any rewrite should use bgbusy() which name better captures the semantics. Show quoted text
> > Why overcomplicate things.
> > I’d have to dig to figure out more, but when we used the automatic TCP > fallback before an unresponsive DNS server caused our resolver code to > hang.
$resolver->tcp_timeout(sensible value); # default is too large to be sensible You will need to set a sensible udp_timeout() as well. Show quoted text
> I’ve actually been playing around with a rewrite of our code and am > trying it now without the bgisready() as you suggest. Initial testing > seems to be fine; we’ll see what comes.
The delay in bgbusy() will be gone in next revision.
Subject: Re: [rt.cpan.org #121897] REQUEST: Make bgbusy() timeout adjustable?
Date: Sat, 3 Jun 2017 12:38:11 -0400
To: bug-Net-DNS [...] rt.cpan.org
From: Felipe Gasper <felipe [...] felipegasper.com>
Show quoted text
> On 3 Jun 2017, at 12:27 PM, Dick Franks via RT <bug-Net-DNS@rt.cpan.org> wrote: > > <URL: https://rt.cpan.org/Ticket/Display.html?id=121897 > > > On Sat Jun 03 11:43:47 2017, felipe@felipegasper.com wrote: >
>> bgisready() could easily handle it, and bgbusy() would still be its >> logical complement.
> > Nonsense! bgisready() is also a predicate. > > bgisready(x) is defined as not(bgbusy(x)) > > and is provided for backward compatibility. Any rewrite should use bgbusy() which name better captures the semantics.
The definition of bgisready() == !bgbusy() seems a suboptimal one since there are more than two states to report: - current wait timed out - connection is ready to read - connection timed out bgisready() can be changed without affecting current implementations. You could, I suppose, do the same with bgbusy(), but multiple falsey returns seems a bit “shakier”. In other words, you could usefully add reporting granularity by adopting this response pattern for bgisready(): undef - current wait timed out 'ready' - connection is ready to read 'timeout' - connection timed out … or something similar. I think the semantics of bgisready() still work: it answers the question, “ready … to do what?”. The trichotomous response pattern above answers that: you either do nothing (undef), you proceed ('ready'), or you give up ('timeout'). Show quoted text
>
>>> Why overcomplicate things.
>> >> I’d have to dig to figure out more, but when we used the automatic TCP >> fallback before an unresponsive DNS server caused our resolver code to >> hang.
> > $resolver->tcp_timeout(sensible value); # default is too large to be sensible > > You will need to set a sensible udp_timeout() as well.
We had both, actually. Ultimately, it’s not what our team was focusing on, and I kind of lost interest in monkey-patching the current resolver code. Show quoted text
>
>> I’ve actually been playing around with a rewrite of our code and am >> trying it now without the bgisready() as you suggest. Initial testing >> seems to be fine; we’ll see what comes.
> > The delay in bgbusy() will be gone in next revision. >
Will that apply also to bgread()? If so, I’d think that a big risky. FWIW. -FG
From: rwfranks [...] acm.org
I have already told you, more than once, that bgbusy() and bgisready() are both predicates. A predicate returns either true or false. Changes to the API require me to be able to provide a rational and coherent argument to other interested parties. There is no point in starting that battle when it cannot be won. I can see some merit in your complaint about the delay inside bgbusy(), and will remove it. That is the _only_ design response there is going to be.
Subject: Re: [rt.cpan.org #121897] REQUEST: Make bgbusy() timeout adjustable?
Date: Thu, 8 Jun 2017 14:45:11 -0500
To: bug-Net-DNS [...] rt.cpan.org
From: Felipe Gasper <felipe [...] felipegasper.com>
Show quoted text
> On 4 Jun 2017, at 12:18 AM, Dick Franks via RT <bug-Net-DNS@rt.cpan.org> wrote: > > <URL: https://rt.cpan.org/Ticket/Display.html?id=121897 > > > I have already told you, more than once, that bgbusy() and bgisready() are both predicates. A predicate returns either true or false.
Nothing is lost by altering the bgisready()’s API as I suggest. Anything that treats bgisready() as a predicate will behave the same way. Newer code, though, can benefit from the more expressive return. It makes good semantic sense because it answers the question, “ready to do what”, which the application has to know in order to distinguish between a timeout and a ready-to-read. In fact, status quo doesn’t seem to offer a way to distinguish between a timeout and a bad read? ------------------------ Status quo: _do_other_stuff() while bgbusy(); #Caller has to call an extra function to determine what actually happened. #This seems suboptimal since N::DNS::R already knows that a timeout happened. if (my $packet = bgread()) { ... } else { #...and even then, I still don’t *know* based on a falsey read #that it was a timeout. die 'Timed out, invalid packet, or something!'; } ------------------------ With proposed change: my $action; _do_other_stuff() until $action = bgisready(); #Now we can fail right away without the extra bgread(). die 'Timed out!' if $action eq 'timeout'; #If we get a failure here, then we can also deal with those knowing #that the failure is NOT a timeout. my $packet = bgread() or do 'Invalid packet or something!'; ------------------------ One could, of course, check errorstring() after the bgbusy() for 'timed out', but the docs don’t seem to describe/guarantee that. I do see that bgbusy() does a bgread() internally and caches the result, so at least it avoids an extra system call, but the apparent ambiguity between a timeout and a bad packet is still there. -FG
From: rwfranks [...] acm.org
The conversation is over, design decisions made. Your feeble argument will not change that.
Subject: Re: [rt.cpan.org #121897] REQUEST: Make bgbusy() timeout adjustable?
Date: Fri, 9 Jun 2017 16:14:09 -0500
To: bug-Net-DNS [...] rt.cpan.org
From: Felipe Gasper <felipe [...] felipegasper.com>
Show quoted text
> On 9 Jun 2017, at 4:07 PM, Dick Franks via RT <bug-Net-DNS@rt.cpan.org> wrote: > > <URL: https://rt.cpan.org/Ticket/Display.html?id=121897 > > > The conversation is over, design decisions made. > Your feeble argument will not change that.
This seems a cop-out; as I illustrated previously, with the code as it stands now, there is no way to distinguish substantially different states based on the responses that the API exposes currently. Casting aspersions at this point will not change it. Anyway. It’s your code. -FG
Resolver per agreed upon modification