The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
CHANGES 9262
LICENSE 1315
MANIFEST 01
META.yml 88
Makefile.PL 1313
README 33
README.mkdn 170170
dist.ini 11
lib/POE/Component/Client/Keepalive.pm 107117
lib/POE/Component/Connection/Keepalive.pm 87
mylib/TestServer.pm 420
t/01_socket_reuse.t 714
t/02_socket_queue.t 86
t/03_each_queue.t 1138
t/04_free_each.t 814
t/05_errors.t 52
t/06_activity.t 63
t/07_keep_alive.t 74
t/08_quick_reuse.t 2237
t/09_timeout.t 74
t/10_resolver.t 1942
t/11_dead_socket.t 63
t/12_extref.t 52
t/13_close.t 74
t/51_reiss_reuse.t 1115
t/release-pod-coverage.t 93
t/release-pod-syntax.t 32
27 files changed (This is a version diff) 560610
@@ -1,138 +1,108 @@
 ==================================================
-Changes from 2011-05-16 00:00:00 +0000 to present.
+Changes from 2013-07-08 00:00:00 +0000 to present.
 ==================================================
 
 ------------------------------------------
-version 0.271 at 2012-05-15 01:46:56 +0000
+version 0.272 at 2014-07-08 17:54:44 +0000
 ------------------------------------------
 
-  Change: d3a27f5934b7a8162b73589820c11ef34f2a272a
+  Change: 96d92a6c75eefdc3fd701c7af9a3255e1f446de5
   Author: Rocco Caputo <rcaputo@cpan.org>
-  Date : 2012-05-14 21:46:18 +0000
+  Date : 2014-07-08 13:45:54 +0000
 
-    Rely upon latest POE::Component::Resolver. 
+    rt.cpan.org 92985. Ideally resolve "Not an ARRAY reference" at
+    shutdown.
 
-  Change: 4280200388131e6addec30ab44b5898eadaf9951
-  Author: Rocco Caputo <rcaputo@cpan.org>
-  Date : 2012-05-14 21:40:07 +0000
-
-    [rt.cpan.org 76776] Fix an edge case where queued requests don't
-    start.
-
-    Sergei Kozunov came through with another great ticket. If two
-    requests for the same host arrive, and the first one fails, the
-    second one will time out in the queue. But only if no other requests
-    are already pending. This change wakes up the queue when a connection
-    fails, causing the subsequent request to be processed. 
+    I haven't encountered the problem myself, but I see where it could
+    happen, thanks to the bug report. This change should fix it, but I
+    haven't got a test case, so no absolute guarantees are made. 
 
-  Change: 52d351f864f722849658a21fa8a54ae78cbea967
+  Change: 3e489b54e73a1ba6e7949f4c96b24bb23bda901f
   Author: Rocco Caputo <rcaputo@cpan.org>
-  Date : 2012-05-14 02:21:00 +0000
+  Date : 2014-07-08 13:42:24 +0000
 
-    [rt.cpan.org 76540] Add stubs for non-blocking SSL.
+    Speed up the test by shutting down the component when done. 
 
-    POE::Component::SSLify is non-blocking now. Add (and comment out)
-    alpha-quality support for this feature. It needs work, and I hope
-    someone who knows it better can help. 
-
-  Change: 3ce660394f2ce76d217b6699551db4a7c541149c
+  Change: a18da3eebd52c4341cca6baa8121607526b02ca1
   Author: Rocco Caputo <rcaputo@cpan.org>
-  Date : 2012-05-13 04:43:58 +0000
-
-    [rt.cpan.org 76987] Cancel timed-out PoCo::Resolver requests.
+  Date : 2013-09-28 09:56:09 +0000
 
-    Sergei Kozunov pointed out that POE::Component::Resolver requests
-    aren't canceled when POE::Component::Client::HTTP requests time out
-    during DNS resolution. Cancel those requests! 
+    Merge pull request #3 from dsteinbrunner/patch-1
 
-------------------------------------------
-version 0.270 at 2012-03-17 00:40:42 +0000
-------------------------------------------
+    Bugtracker metadata fix. 
 
-  Change: 8298bbf560abb6f7d3f485e0eb532f17784fab6e
-  Author: Rocco Caputo <rcaputo@cpan.org>
-  Date : 2012-03-16 20:40:42 +0000
+  Change: d5c4b1e9d2f16a2f06e11b674e6d5273f5d9c964
+  Author: David Steinbrunner <dsteinbrunner@pobox.com>
+  Date : 2013-09-25 05:24:04 +0000
 
-    Apply Markus Jansen's patch to add a TCP protocol resolver hint.
+    bugtracker metadata fix 
 
-    Markus reports that this resolves rampant errors on solaris systems.
-    I've verified that it doesn't break tests, which is bonus! Thanks! 
-
-------------------------------------------
-version 0.269 at 2012-03-05 03:00:25 +0000
-------------------------------------------
-
-  Change: 38b4299562eb33393d00a17bbd902c95af881d45
+  Change: 4f3529282049828691feed6fa726d90ba1e78176
   Author: Rocco Caputo <rcaputo@cpan.org>
-  Date : 2012-03-04 22:00:25 +0000
+  Date : 2013-09-07 18:06:06 +0000
 
-    Need the absolutely latest POE::Component::Resolver as of this
-    writing. 
+    Minor syntax cleanups. Nothing functionally significant. 
 
-  Change: 6ad518a932c733f2eeac97837f4e313abf0c993c
+  Change: c3e8492b933336765287302fb5a7fc54ddce0347
   Author: Rocco Caputo <rcaputo@cpan.org>
-  Date : 2012-03-04 21:59:35 +0000
-
-    [rt.cpan.org 73353] Use ports instead of schemes when resolving
-    hosts.
+  Date : 2013-09-07 17:49:05 +0000
 
-    Solaris (and probably other systems) don't have an /etc/services
-    entry for http, so relying on the lookup fails here. Luckily the user
-    also provides a port (which may or may not be symbolic). I'll use
-    that for now and see where it gets me.
+    Improve thread safety.
 
-    Thank you, Michael Lackhoff, for reporting this bug. 
+    Move away from using stringified references. The references can
+    change when threads come into play, but the saved string versions
+    won't. This includes using fork() on Windows. 
 
-  Change: 39c1651caf89ed55f8165ac55bff68869011207b
+  Change: c8e993b3b8345644bfa49e8fac114760d0224303
   Author: Rocco Caputo <rcaputo@cpan.org>
-  Date : 2012-03-04 21:38:36 +0000
+  Date : 2013-09-07 17:44:49 +0000
 
-    Add auto-tagging and auto-versioning to dist.ini. 
+    Consolidate C<use constant> statements. 
 
-  Change: e8965b65a23ee3fa969cc9f2ee4ee8e1ea6d3e7f
+  Change: 838ec7f439841a60ccd744b2c60e7df94089ec96
   Author: Rocco Caputo <rcaputo@cpan.org>
-  Date : 2011-12-16 00:12:41 +0000
+  Date : 2013-07-15 22:20:47 +0000
 
-    Merge pull request #2 from bingos/master
+    Log why connection tests fail.
 
-    Use Net::IP::Minimal instead of Net::IP 
+    Most cpantesters.org failure reports are of the form "connection
+    failed" without explaining why. Explain why. 
 
-  Change: bf7abd1cda69cd022e37c46ececcacdb1a6d2048
-  Author: Chris 'BinGOs' Williams <chris@bingosnet.co.uk>
-  Date : 2011-11-17 21:39:14 +0000
+  Change: e3bb8e929fed59ef7dd166a9a92c47c047f07205
+  Author: Rocco Caputo <rcaputo@cpan.org>
+  Date : 2013-07-15 03:10:15 +0000
 
-    Use Net::IP::Minimal instead of Net::IP
+    Resolve most bind() conflicts by using port 0.
 
-    Net::IP consumes a fair chunk of memory, Net::DNS stopped using it
-    see https://rt.cpan.org/Public/Bug/Display.html?id=24525 
+    I was using random ports, which are mostly okay, but over the course
+    of hundreds of cpantesters.org reports, enough showed up to make it a
+    concern 
 
-------------------------------------------
-version 0_268 at 2011-07-30 08:54:36 +0000
-------------------------------------------
-
-  Change: c53106ea6c8aa079eb251a4dc9707d23492f7e1e
+  Change: 20d1dce836f7ecba7ae4cbb0449fa4540e1c6e92
   Author: Rocco Caputo <rcaputo@cpan.org>
-  Date : 2011-07-30 04:54:36 +0000
+  Date : 2013-07-15 02:37:31 +0000
 
-    Bump revision and dependency for release. 
+    Remove a TestServer shutdown race condition.
 
-  Change: b791c0bdc8cd29f3969b5cffcebfa2f5ab057eb5
-  Author: Rocco Caputo <rcaputo@cpan.org>
-  Date : 2011-07-30 04:30:12 +0000
+    Counted after 14 cpantesters.org failures of the form "Failed test
+    'first request honored asynchronously'". Added detailed error
+    information to the failure. If it happens again, I'll be better
+    prepared to fix it.
 
-    Multi-line NAME sections corrupt the VERSION/NAME section ordering.
-    I'm not sure why or which plugin is doing it, but making the NAME
-    test one line is a serviceable workaround.
+    Stopped relying on the order of first/second connection callbacks.
+    Previously, if the second fired first, we'd shut down the TestServer
+    too early. The first connection would then fail because.
 
-    Resolves rt.cpan.org ticket 69235, reported by Debian developer
-    Gregor Hermann. 
+    Meanwhile, always shutdown the connection manager (not just after the
+    second response). Each session has its own, and they both need to go.
+    Otherwise the program waits the obligatory connection pool timeout. 
 
-  Change: 65eb566f05d5f3fadebd20d41c4fc928bc596e2c
-  Author: Chris 'BinGOs' Williams <chris@bingosnet.co.uk>
-  Date : 2011-07-25 22:54:59 +0000
+  Change: 776e56c9af244b0ea35f12f9e4298654548d32cf
+  Author: Rocco Caputo <rcaputo@cpan.org>
+  Date : 2012-06-03 03:08:19 +0000
 
-    Address [rt.cpan.org #69519] "resolve() on shutdown resolver" errors 
+    Add more values to some debugging statements. 
 
 =================================================
-Plus 29 releases after 2011-05-16 00:00:00 +0000.
+Plus 33 releases after 2013-07-08 00:00:00 +0000.
 =================================================
@@ -1,4 +1,4 @@
-This software is copyright (c) 2012 by Rocco Caputo.
+This software is copyright (c) 2014 by Rocco Caputo.
 
 This is free software; you can redistribute it and/or modify it under
 the same terms as the Perl 5 programming language system itself.
@@ -12,21 +12,22 @@ b) the "Artistic License"
 
 --- The GNU General Public License, Version 1, February 1989 ---
 
-This software is Copyright (c) 2012 by Rocco Caputo.
+This software is Copyright (c) 2014 by Rocco Caputo.
 
 This is free software, licensed under:
 
   The GNU General Public License, Version 1, February 1989
 
-		    GNU GENERAL PUBLIC LICENSE
-		     Version 1, February 1989
+                    GNU GENERAL PUBLIC LICENSE
+                     Version 1, February 1989
 
  Copyright (C) 1989 Free Software Foundation, Inc.
-                59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+ 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
  Everyone is permitted to copy and distribute verbatim copies
  of this license document, but changing it is not allowed.
 
-			    Preamble
+                            Preamble
 
   The license agreements of most software companies try to keep users
 at the mercy of those companies.  By contrast, our General Public
@@ -67,7 +68,7 @@ authors' reputations.
   The precise terms and conditions for copying, distribution and
 modification follow.
 
-		    GNU GENERAL PUBLIC LICENSE
+                    GNU GENERAL PUBLIC LICENSE
    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 
   0. This License Agreement applies to any program or other work which
@@ -185,7 +186,7 @@ make exceptions for this.  Our decision will be guided by the two goals
 of preserving the free status of all derivatives of our free software and
 of promoting the sharing and reuse of software generally.
 
-			    NO WARRANTY
+                            NO WARRANTY
 
   9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
 FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
@@ -207,9 +208,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
 PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGES.
 
-		     END OF TERMS AND CONDITIONS
+                     END OF TERMS AND CONDITIONS
 
-	Appendix: How to Apply These Terms to Your New Programs
+        Appendix: How to Apply These Terms to Your New Programs
 
   If you develop a new program, and you want it to be of the greatest
 possible use to humanity, the best way to achieve this is to make it
@@ -235,8 +236,9 @@ the exclusion of warranty; and each file should have at least the
     GNU General Public License for more details.
 
     You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software Foundation,
-    Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
+
 
 Also add information on how to contact you by electronic and paper mail.
 
@@ -270,7 +272,7 @@ That's all there is to it!
 
 --- The Artistic License 1.0 ---
 
-This software is Copyright (c) 2012 by Rocco Caputo.
+This software is Copyright (c) 2014 by Rocco Caputo.
 
 This is free software, licensed under:
 
@@ -1,3 +1,4 @@
+# This file was automatically generated by Dist::Zilla::Plugin::Manifest v5.019.
 CHANGES
 LICENSE
 MANIFEST
@@ -4,19 +4,19 @@ author:
   - 'Rocco Caputo <rcaputo@cpan.org>'
 build_requires: {}
 configure_requires:
-  ExtUtils::MakeMaker: 6.30
+  ExtUtils::MakeMaker: '6.30'
 dynamic_config: 0
-generated_by: 'Dist::Zilla version 4.300016, CPAN::Meta::Converter version 2.120921'
+generated_by: 'Dist::Zilla version 5.019, CPAN::Meta::Converter version 2.141520'
 license: perl
 meta-spec:
   url: http://module-build.sourceforge.net/META-spec-v1.4.html
-  version: 1.4
+  version: '1.4'
 name: POE-Component-Client-Keepalive
 requires:
-  Net::IP::Minimal: 0.02
-  POE: 1.311
-  POE::Component::Resolver: 0.917
+  Net::IP::Minimal: '0.02'
+  POE: '1.311'
+  POE::Component::Resolver: '0.917'
 resources:
-  bugtracker: http://rt.cpan.org/Public/Dist/Display.html?POE-Component-Client-Keepalive
+  bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=POE-Component-Client-Keepalive
   repository: git://github.com/rcaputo/poe-component-client-keepalive.git
-version: 0.271
+version: '0.272'
@@ -1,4 +1,5 @@
 
+# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v5.019.
 use strict;
 use warnings;
 
@@ -11,7 +12,6 @@ use ExtUtils::MakeMaker 6.30;
 my %WriteMakefileArgs = (
   "ABSTRACT" => "manage connections, with keep-alive",
   "AUTHOR" => "Rocco Caputo <rcaputo\@cpan.org>",
-  "BUILD_REQUIRES" => {},
   "CONFIGURE_REQUIRES" => {
     "ExtUtils::MakeMaker" => "6.30"
   },
@@ -24,24 +24,24 @@ my %WriteMakefileArgs = (
     "POE" => "1.311",
     "POE::Component::Resolver" => "0.917"
   },
-  "VERSION" => "0.271",
+  "VERSION" => "0.272",
   "test" => {
     "TESTS" => "t/*.t"
   }
 );
 
 
-unless ( eval { ExtUtils::MakeMaker->VERSION(6.56) } ) {
-  my $br = delete $WriteMakefileArgs{BUILD_REQUIRES};
-  my $pp = $WriteMakefileArgs{PREREQ_PM};
-  for my $mod ( keys %$br ) {
-    if ( exists $pp->{$mod} ) {
-      $pp->{$mod} = $br->{$mod} if $br->{$mod} > $pp->{$mod};
-    }
-    else {
-      $pp->{$mod} = $br->{$mod};
-    }
-  }
+my %FallbackPrereqs = (
+  "Net::IP::Minimal" => "0.02",
+  "POE" => "1.311",
+  "POE::Component::Resolver" => "0.917"
+);
+
+
+unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) {
+  delete $WriteMakefileArgs{TEST_REQUIRES};
+  delete $WriteMakefileArgs{BUILD_REQUIRES};
+  $WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs;
 }
 
 delete $WriteMakefileArgs{CONFIGURE_REQUIRES}
@@ -2,7 +2,7 @@ NAME
     POE::Component::Client::Keepalive - manage connections, with keep-alive
 
 VERSION
-    version 0.271
+    version 0.272
 
 SYNOPSIS
       use warnings;
@@ -24,9 +24,9 @@ SYNOPSIS
       exit;
 
       sub start {
-        $_[HEAP]->{ka} = POE::Component::Client::Keepalive->new();
+        $_[HEAP]{ka} = POE::Component::Client::Keepalive->new();
 
-        $_[HEAP]->{ka}->allocate(
+        $_[HEAP]{ka}->allocate(
           scheme  => "http",
           addr    => "127.0.0.1",
           port    => 9999,
@@ -4,81 +4,81 @@ POE::Component::Client::Keepalive - manage connections, with keep-alive
 
 # VERSION
 
-version 0.271
+version 0.272
 
 # SYNOPSIS
 
-  use warnings;
-  use strict;
+    use warnings;
+    use strict;
 
-  use POE;
-  use POE::Component::Client::Keepalive;
+    use POE;
+    use POE::Component::Client::Keepalive;
 
-  POE::Session->create(
-    inline_states => {
-      _start    => \&start,
-      got_conn  => \&got_conn,
-      got_error => \&handle_error,
-      got_input => \&handle_input,
-    }
-  );
-
-  POE::Kernel->run();
-  exit;
-
-  sub start {
-    $_[HEAP]->{ka} = POE::Component::Client::Keepalive->new();
-
-    $_[HEAP]->{ka}->allocate(
-      scheme  => "http",
-      addr    => "127.0.0.1",
-      port    => 9999,
-      event   => "got_conn",
-      context => "arbitrary data (even a reference) here",
-      timeout => 60,
+    POE::Session->create(
+      inline_states => {
+        _start    => \&start,
+        got_conn  => \&got_conn,
+        got_error => \&handle_error,
+        got_input => \&handle_input,
+      }
     );
 
-    print "Connection is in progress.\n";
-  }
+    POE::Kernel->run();
+    exit;
 
-  sub got_conn {
-    my ($kernel, $heap, $response) = @_[KERNEL, HEAP, ARG0];
+    sub start {
+      $_[HEAP]{ka} = POE::Component::Client::Keepalive->new();
 
-    my $conn    = $response->{connection};
-    my $context = $response->{context};
+      $_[HEAP]{ka}->allocate(
+        scheme  => "http",
+        addr    => "127.0.0.1",
+        port    => 9999,
+        event   => "got_conn",
+        context => "arbitrary data (even a reference) here",
+        timeout => 60,
+      );
 
-    if (defined $conn) {
-      if ($response->{from_cache}) {
-        print "Connection was established immediately.\n";
-      }
-      else {
-        print "Connection was established asynchronously.\n";
+      print "Connection is in progress.\n";
+    }
+
+    sub got_conn {
+      my ($kernel, $heap, $response) = @_[KERNEL, HEAP, ARG0];
+
+      my $conn    = $response->{connection};
+      my $context = $response->{context};
+
+      if (defined $conn) {
+        if ($response->{from_cache}) {
+          print "Connection was established immediately.\n";
+        }
+        else {
+          print "Connection was established asynchronously.\n";
+        }
+
+        $conn->start(
+          InputEvent => "got_input",
+          ErrorEvent => "got_error",
+        );
+        return;
       }
 
-      $conn->start(
-        InputEvent => "got_input",
-        ErrorEvent => "got_error",
+      print(
+        "Connection could not be established: ",
+        "$response->{function} error $response->{error_num}: ",
+        "$response->{error_str}\n"
       );
-      return;
     }
 
-    print(
-      "Connection could not be established: ",
-      "$response->{function} error $response->{error_num}: ",
-      "$response->{error_str}\n"
-    );
-  }
-
-  sub handle_input {
-    my $input = $_[ARG0];
-    print "$input\n";
-  }
+    sub handle_input {
+      my $input = $_[ARG0];
+      print "$input\n";
+    }
 
-  sub handle_error {
-    my $heap = $_[HEAP];
-    delete $heap->{connection};
-    $heap->{ka}->shutdown();
-  }
+    sub handle_error {
+      my $heap = $_[HEAP];
+      delete $heap->{connection};
+      $heap->{ka}->shutdown();
+    }
 
 # DESCRIPTION
 
@@ -90,169 +90,169 @@ one-shot connections would probably be silly.
 
 - new
 
-Creates a new keepalive connection manager.  A program may contain
-several connection managers.  Each will operate independently of the
-others.  None will know about the limits set in the others, so it's
-possible to overrun your file descriptors for a process if you're not
-careful.
+    Creates a new keepalive connection manager.  A program may contain
+    several connection managers.  Each will operate independently of the
+    others.  None will know about the limits set in the others, so it's
+    possible to overrun your file descriptors for a process if you're not
+    careful.
 
-new() takes up to five parameters.  All of them are optional.
+    new() takes up to five parameters.  All of them are optional.
 
-To limit the number of simultaneous connections to a particular host
-(defined by a combination of scheme, address and port):
+    To limit the number of simultaneous connections to a particular host
+    (defined by a combination of scheme, address and port):
 
-  max_per_host => $max_simultaneous_host_connections, # defaults to 4
+        max_per_host => $max_simultaneous_host_connections, # defaults to 4
 
-To limit the overall number of connections that may be open at once,
-use
+    To limit the overall number of connections that may be open at once,
+    use
 
-  max_open     => $maximum_open_connections, # defaults to 128
+        max_open     => $maximum_open_connections, # defaults to 128
 
-Programs are required to give connections back to the manager when
-they are done.  See the free() method for how that works.  The
-connection manager will keep connections alive for a period of time
-before recycling them.  The maximum keep-alive time may be set with
+    Programs are required to give connections back to the manager when
+    they are done.  See the free() method for how that works.  The
+    connection manager will keep connections alive for a period of time
+    before recycling them.  The maximum keep-alive time may be set with
 
-  keep_alive   => $seconds_to_keep_free_conns_alive, # defaults to 15
+        keep_alive   => $seconds_to_keep_free_conns_alive, # defaults to 15
 
-Programs may not want to wait a long time for a connection to be
-established.  They can set the request timeout to alter how long the
-component holds a request before generating an error.
+    Programs may not want to wait a long time for a connection to be
+    established.  They can set the request timeout to alter how long the
+    component holds a request before generating an error.
 
-  timeout      => $seconds_to_process_a_request, # defaults to 120
+        timeout      => $seconds_to_process_a_request, # defaults to 120
 
-Specify a bind_address to bind all client sockets to a particular
-local address.  The value of bind_address will be passed directly to
-POE::Wheel::SocketFactory.  See that module's documentation for
-implementation details.
+    Specify a bind\_address to bind all client sockets to a particular
+    local address.  The value of bind\_address will be passed directly to
+    POE::Wheel::SocketFactory.  See that module's documentation for
+    implementation details.
 
 - allocate
 
-Allocate a new connection.  Allocate() will return a request ID
-immediately.  The allocated connection, however, will be posted back
-to the requesting session.  This happens even if the connection was
-found in the component's keep-alive cache.  It's a bit slower, but the
-use cases are cleaner that way.
+    Allocate a new connection.  Allocate() will return a request ID
+    immediately.  The allocated connection, however, will be posted back
+    to the requesting session.  This happens even if the connection was
+    found in the component's keep-alive cache.  It's a bit slower, but the
+    use cases are cleaner that way.
 
-Allocate() requires five parameters and has an optional sixth.
+    Allocate() requires five parameters and has an optional sixth.
 
-Specify the scheme that will be used to communicate on the connection
-(typically http or https).  The scheme is required, but you're free to
-make something up here.  It's used internally to differentiate
-different types of socket (e.g., ssl vs. cleartext) on the same
-address and port.
+    Specify the scheme that will be used to communicate on the connection
+    (typically http or https).  The scheme is required, but you're free to
+    make something up here.  It's used internally to differentiate
+    different types of socket (e.g., ssl vs. cleartext) on the same
+    address and port.
 
-  scheme  => $connection_scheme,
+        scheme  => $connection_scheme,
 
-Request a connection to a particular address and port.  The address
-and port must be numeric.  Both the address and port are required.
+    Request a connection to a particular address and port.  The address
+    and port must be numeric.  Both the address and port are required.
 
-  address => $remote_address,
-  port    => $remote_port,
+        address => $remote_address,
+        port    => $remote_port,
 
-Specify an name of the event to post when an asynchronous response is
-ready.  This is of course required.
+    Specify an name of the event to post when an asynchronous response is
+    ready.  This is of course required.
 
-  event   => $return_event,
+        event   => $return_event,
 
-Set the connection timeout, in seconds.  The connection manager will
-post back an error message if it can't establish a connection within
-the requested time.  This parameter is optional.  It will default to
-the master timeout provided to the connection manager's constructor.
+    Set the connection timeout, in seconds.  The connection manager will
+    post back an error message if it can't establish a connection within
+    the requested time.  This parameter is optional.  It will default to
+    the master timeout provided to the connection manager's constructor.
 
-  timeout => $connect_timeout,
+        timeout => $connect_timeout,
 
-Specify additional contextual data.  The context defines the
-connection's purpose.  It is used to maintain continuity between a
-call to allocate() and an asynchronous response.  A context is
-extremely handy, but it's optional.
+    Specify additional contextual data.  The context defines the
+    connection's purpose.  It is used to maintain continuity between a
+    call to allocate() and an asynchronous response.  A context is
+    extremely handy, but it's optional.
 
-  context => $context_data,
+        context => $context_data,
 
-In summary:
+    In summary:
 
-  $mgr->allocate(
-    scheme   => "http",
-    address  => "127.0.0.1",
-    port     => 80,
-    event    => "got_a_connection",
-    context  => \%connection_context,
-  );
+        $mgr->allocate(
+          scheme   => "http",
+          address  => "127.0.0.1",
+          port     => 80,
+          event    => "got_a_connection",
+          context  => \%connection_context,
+        );
 
-The response event ("got_a_connection" in this example) contains
-several fields, passed as a list of key/value pairs.  The list may be
-assigned to a hash for convenience:
+    The response event ("got\_a\_connection" in this example) contains
+    several fields, passed as a list of key/value pairs.  The list may be
+    assigned to a hash for convenience:
 
-  sub got_a_connection {
-    my %response = @_[ARG0..$#_];
-    ...;
-  }
+        sub got_a_connection {
+          my %response = @_[ARG0..$#_];
+          ...;
+        }
 
-Four of the fields exist to echo back your data:
+    Four of the fields exist to echo back your data:
 
-  $response{address}    = $your_request_address;
-  $response{context}    = $your_request_context;
-  $response{port}       = $your_request_port;
-  $response{scheme}     = $your_request_scheme;
+        $response{address}    = $your_request_address;
+        $response{context}    = $your_request_context;
+        $response{port}       = $your_request_port;
+        $response{scheme}     = $your_request_scheme;
 
-One field returns the connection object if the connection was
-successful, or undef if there was a failure:
+    One field returns the connection object if the connection was
+    successful, or undef if there was a failure:
 
-  $response{connection} = $new_socket_handle;
+        $response{connection} = $new_socket_handle;
 
-On success, another field tells you whether the connection contains
-all new materials.  That is, whether the connection has been recycled
-from the component's cache or created anew.
+    On success, another field tells you whether the connection contains
+    all new materials.  That is, whether the connection has been recycled
+    from the component's cache or created anew.
 
-  $response{from_cache} = $status;
+        $response{from_cache} = $status;
 
-The from_cache status may be "immediate" if the connection was
-immediately available from the cache.  It will be "deferred" if the
-connection was reused, but another user had to release it first.
-Finally, from_cache will be false if the connection had to be created
-to satisfy allocate().
+    The from\_cache status may be "immediate" if the connection was
+    immediately available from the cache.  It will be "deferred" if the
+    connection was reused, but another user had to release it first.
+    Finally, from\_cache will be false if the connection had to be created
+    to satisfy allocate().
 
-Three other fields return error information if the connection failed.
-They are not present if the connection was successful.
+    Three other fields return error information if the connection failed.
+    They are not present if the connection was successful.
 
-  $response{function}   = $name_of_failing_function;
-  $response{error_num}  = $! as a number;
-  $response{error_str}  = $! as a string;
+        $response{function}   = $name_of_failing_function;
+        $response{error_num}  = $! as a number;
+        $response{error_str}  = $! as a string;
 
 - free
 
-Free() notifies the connection manager when connections are free to be
-reused.  Freed connections are entered into the keep-alive pool and
-may be returned by subsequent allocate() calls.
+    Free() notifies the connection manager when connections are free to be
+    reused.  Freed connections are entered into the keep-alive pool and
+    may be returned by subsequent allocate() calls.
 
-  $mgr->free($socket);
+        $mgr->free($socket);
 
-For now free() is called with a socket, not a connection object.  This
-is usually not a problem since POE::Component::Connection::Keepalive
-objects call free() for you when they are destroyed.
+    For now free() is called with a socket, not a connection object.  This
+    is usually not a problem since POE::Component::Connection::Keepalive
+    objects call free() for you when they are destroyed.
 
-Not calling free() will cause a program to leak connections.  This is
-also not generally a problem, since free() is called automatically
-whenever connection objects are destroyed.
+    Not calling free() will cause a program to leak connections.  This is
+    also not generally a problem, since free() is called automatically
+    whenever connection objects are destroyed.
 
 - deallocate
 
-Cancel a connection that has not yet been established.  Requires one
-parameter, the request ID returned by allocate().
+    Cancel a connection that has not yet been established.  Requires one
+    parameter, the request ID returned by allocate().
 
 - shutdown
 
-The keep-alive pool requires connections to be active internally.
-This may keep a program active even when all connections are idle.
-The shutdown() method forces the connection manager to clear its
-keep-alive pool, allowing a program to terminate gracefully.
+    The keep-alive pool requires connections to be active internally.
+    This may keep a program active even when all connections are idle.
+    The shutdown() method forces the connection manager to clear its
+    keep-alive pool, allowing a program to terminate gracefully.
 
-  $mgr->shutdown();
+        $mgr->shutdown();
 
 # SEE ALSO
 
-[POE](http://search.cpan.org/perldoc?POE)
-[POE::Component::Connection::Keepalive](http://search.cpan.org/perldoc?POE::Component::Connection::Keepalive)
+[POE](https://metacpan.org/pod/POE)
+[POE::Component::Connection::Keepalive](https://metacpan.org/pod/POE::Component::Connection::Keepalive)
 
 # LICENSE
 
@@ -282,4 +282,4 @@ http://github.com/rcaputo/poe-component-client-keepalive
 
 # OTHER RESOURCES
 
-http://search.cpan.org/dist/POE-Component-Client-Keepalive/
\ No newline at end of file
+http://search.cpan.org/dist/POE-Component-Client-Keepalive/
@@ -9,7 +9,7 @@ POE                       = 1.311
 POE::Component::Resolver  = 0.917
 
 [MetaResources]
-bugtracker        = http://rt.cpan.org/Public/Dist/Display.html?POE-Component-Client-Keepalive
+bugtracker        = http://rt.cpan.org/Public/Dist/Display.html?Name=POE-Component-Client-Keepalive
 repository        = https://github.com/rcaputo/poe-component-client-keepalive
 
 [Repository]
@@ -1,9 +1,6 @@
 package POE::Component::Client::Keepalive;
-{
-  $POE::Component::Client::Keepalive::VERSION = '0.271';
-}
 # vim: ts=2 sw=2 expandtab
-
+$POE::Component::Client::Keepalive::VERSION = '0.272';
 use warnings;
 use strict;
 
@@ -24,8 +21,11 @@ eval {
 };
 
 use constant DEBUG => 0;
-use constant DEBUG_DNS => DEBUG || 0;
-use constant DEBUG_DEALLOCATE => DEBUG || 0;
+
+use constant {
+  DEBUG_DNS        => (DEBUG || 0),
+  DEBUG_DEALLOCATE => (DEBUG || 0),
+};
 
 use constant TCP_PROTO => scalar(getprotobyname "tcp") || (
   die "getprotobyname('tcp') failed: $!"
@@ -55,42 +55,43 @@ my $instances = 0;
 # them arrays.  These constants define offsets into those arrays, and
 # the comments document them.
 
-                                 # @$self = (
-use constant SF_POOL      => 0;  #   \%socket_pool,
-use constant SF_QUEUE     => 1;  #   \@request_queue,
-use constant SF_USED      => 2;  #   \%sockets_in_use,
-use constant SF_WHEELS    => 3;  #   \%wheels_by_id,
-use constant SF_USED_EACH => 4;  #   \%count_by_triple,
-use constant SF_MAX_OPEN  => 5;  #   $max_open_count,
-use constant SF_MAX_HOST  => 6;  #   $max_per_host,
-use constant SF_SOCKETS   => 7;  #   \%socket_xref,
-use constant SF_KEEPALIVE => 8;  #   $keep_alive_secs,
-use constant SF_TIMEOUT   => 9;  #   $default_request_timeout,
-use constant SF_RESOLVER  => 10; #   $poco_client_dns_object,
-use constant SF_SHUTDOWN  => 11; #   $shutdown_flag,
-use constant SF_REQ_INDEX => 12; #   \%request_id_to_wheel_id,
-use constant SF_BIND_ADDR => 13; #   $bind_address,
-                                 # );
-
-                                 # $socket_xref{$socket} = [
-use constant SK_KEY       => 0;  #   $conn_key,
-use constant SK_TIMER     => 1;  #   $idle_timer,
-                                 # ];
+use constant {         # @$self = (
+  SF_POOL       => 0,  #   \%socket_pool,
+  SF_QUEUE      => 1,  #   \@request_queue,
+  SF_USED       => 2,  #   \%sockets_in_use,
+  SF_WHEELS     => 3,  #   \%wheels_by_id,
+  SF_USED_EACH  => 4,  #   \%count_by_triple,
+  SF_MAX_OPEN   => 5,  #   $max_open_count,
+  SF_MAX_HOST   => 6,  #   $max_per_host,
+  SF_SOCKETS    => 7,  #   \%socket_xref,
+  SF_KEEPALIVE  => 8,  #   $keep_alive_secs,
+  SF_TIMEOUT    => 9,  #   $default_request_timeout,
+  SF_RESOLVER   => 10, #   $poco_client_dns_object,
+  SF_SHUTDOWN   => 11, #   $shutdown_flag,
+  SF_REQ_INDEX  => 12, #   \%request_id_to_wheel_id,
+  SF_BIND_ADDR  => 13, #   $bind_address,
+  SF_ALIAS      => 14, #   $embedded_session_alias
+};                     # );
+
+use constant {       # $socket_xref{$socket} = [
+  SK_KEY       => 0, #   $conn_key,
+  SK_TIMER     => 1, #   $idle_timer,
+};                   # ];
 
 # $count_by_triple{$conn_key} = $conn_count;
 
-                                 # $wheels_by_id{$wheel_id} = [
-use constant WHEEL_WHEEL   => 0; #   $wheel_object,
-use constant WHEEL_REQUEST => 1; #   $request,
-                                 # ];
+use constant {        # $wheels_by_id{$wheel_id} = [
+  WHEEL_WHEEL   => 0, #   $wheel_object,
+  WHEEL_REQUEST => 1, #   $request,
+};                    # ];
 
 # $socket_pool{$conn_key}{$socket} = $socket;
 
-                                 # $sockets_in_use{$socket} = (
-use constant USED_SOCKET => 0;   #   $socket_handle,
-use constant USED_TIME   => 1;   #   $allocation_time,
-use constant USED_KEY    => 2;   #   $conn_key,
-                                 # );
+use constant {      # $sockets_in_use{$socket} = (
+  USED_SOCKET => 0, #   $socket_handle,
+  USED_TIME   => 1, #   $allocation_time,
+  USED_KEY    => 2, #   $conn_key,
+};                  # );
 
 # @request_queue = (
 #   $request,
@@ -98,27 +99,27 @@ use constant USED_KEY    => 2;   #   $conn_key,
 #   ....
 # );
 
-                                    # $request = [
-use constant RQ_SESSION     => 0;   #   $request_session,
-use constant RQ_EVENT       => 1;   #   $request_event,
-use constant RQ_SCHEME      => 2;   #   $request_scheme,
-use constant RQ_ADDRESS     => 3;   #   $request_address,
-use constant RQ_IP          => 4;   #   $request_ip,
-use constant RQ_PORT        => 5;   #   $request_port,
-use constant RQ_CONN_KEY    => 6;   #   $request_connection_key,
-use constant RQ_CONTEXT     => 7;   #   $request_context,
-use constant RQ_TIMEOUT     => 8;   #   $request_timeout,
-use constant RQ_START       => 9;   #   $request_start_time,
-use constant RQ_TIMER_ID    => 10;  #   $request_timer_id,
-use constant RQ_WHEEL_ID    => 11;  #   $request_wheel_id,
-use constant RQ_ACTIVE      => 12;  #   $request_is_active,
-use constant RQ_ID          => 13;  #   $request_id,
-use constant RQ_ADDR_FAM    => 14;  #   $request_address_family,
-use constant RQ_FOR_SCHEME  => 15;  #   $...
-use constant RQ_FOR_ADDRESS => 16;  #   $...
-use constant RQ_FOR_PORT    => 17;  #   $...
-use constant RQ_RESOLVER_ID => 18;  #   $resolver_request_id,
-                                    # ];
+use constant {          # $request = [
+  RQ_SESSION     => 0,  #   $request_session,
+  RQ_EVENT       => 1,  #   $request_event,
+  RQ_SCHEME      => 2,  #   $request_scheme,
+  RQ_ADDRESS     => 3,  #   $request_address,
+  RQ_IP          => 4,  #   $request_ip,
+  RQ_PORT        => 5,  #   $request_port,
+  RQ_CONN_KEY    => 6,  #   $request_connection_key,
+  RQ_CONTEXT     => 7,  #   $request_context,
+  RQ_TIMEOUT     => 8,  #   $request_timeout,
+  RQ_START       => 9,  #   $request_start_time,
+  RQ_TIMER_ID    => 10, #   $request_timer_id,
+  RQ_WHEEL_ID    => 11, #   $request_wheel_id,
+  RQ_ACTIVE      => 12, #   $request_is_active,
+  RQ_ID          => 13, #   $request_id,
+  RQ_ADDR_FAM    => 14, #   $request_address_family,
+  RQ_FOR_SCHEME  => 15, #   $...
+  RQ_FOR_ADDRESS => 16, #   $...
+  RQ_FOR_PORT    => 17, #   $...
+  RQ_RESOLVER_ID => 18, #   $resolver_request_id,
+};                      # ];
 
 # Create a connection manager.
 
@@ -139,6 +140,8 @@ sub new {
     croak "new() doesn't accept: @unknown";
   }
 
+  my $alias = "POE::Component::Client::Keepalive::" . ++$current_id;
+
   my $self = bless [
     { },                # SF_POOL
     [ ],                # SF_QUEUE
@@ -154,50 +157,54 @@ sub new {
     undef,              # SF_SHUTDOWN
     undef,              # SF_REQ_INDEX
     $bind_address,      # SF_BIND_ADDR
+    undef,              # SF_ALIAS
   ], $class;
 
-  $default_resolver = $resolver
-    if $resolver && eval { $resolver->isa('POE::Component::Resolver') };
+  $default_resolver = $resolver if (
+    $resolver and eval { $resolver->isa('POE::Component::Resolver') }
+  );
 
   $self->[SF_RESOLVER] = (
     $default_resolver ||= POE::Component::Resolver->new()
   );
 
-  POE::Session->create(
+  my $session = POE::Session->create(
     object_states => [
       $self => {
-        _start               => "_ka_initialize",
-        _stop                => "_ka_stopped",
-        ka_add_to_queue      => "_ka_add_to_queue",
+        _start                 => "_ka_initialize",
+        _stop                  => "_ka_stopped",
+        ka_add_to_queue        => "_ka_add_to_queue",
         ka_cancel_dns_response => "_ka_cancel_dns_response",
-        ka_conn_failure      => "_ka_conn_failure",
-        ka_conn_success      => "_ka_conn_success",
-        ka_deallocate        => "_ka_deallocate",
-        ka_dns_response      => "_ka_dns_response",
-        ka_keepalive_timeout => "_ka_keepalive_timeout",
-        ka_reclaim_socket    => "_ka_reclaim_socket",
-        ka_relinquish_socket => "_ka_relinquish_socket",
-        ka_request_timeout   => "_ka_request_timeout",
-        ka_resolve_request   => "_ka_resolve_request",
-        ka_set_timeout       => "_ka_set_timeout",
-        ka_shutdown          => "_ka_shutdown",
-        ka_socket_activity   => "_ka_socket_activity",
-        ka_wake_up           => "_ka_wake_up",
+        ka_conn_failure        => "_ka_conn_failure",
+        ka_conn_success        => "_ka_conn_success",
+        ka_deallocate          => "_ka_deallocate",
+        ka_dns_response        => "_ka_dns_response",
+        ka_keepalive_timeout   => "_ka_keepalive_timeout",
+        ka_reclaim_socket      => "_ka_reclaim_socket",
+        ka_relinquish_socket   => "_ka_relinquish_socket",
+        ka_request_timeout     => "_ka_request_timeout",
+        ka_resolve_request     => "_ka_resolve_request",
+        ka_set_timeout         => "_ka_set_timeout",
+        ka_shutdown            => "_ka_shutdown",
+        ka_socket_activity     => "_ka_socket_activity",
+        ka_wake_up             => "_ka_wake_up",
       },
     ],
   );
 
+  $self->[SF_ALIAS] = ref($self) . "::" . $session->ID();
+
   return $self;
 }
 
 # Initialize the hidden session behind this component.
-# Set an alias so the public methods can send it messages easily.
+# Rendezvous with the object via a mutually agreed upon alias.
 
 sub _ka_initialize {
   my ($object, $kernel, $heap) = @_[OBJECT, KERNEL, HEAP];
   $instances++;
-  $heap->{resolve} = { };
-  $kernel->alias_set("$object");
+  $heap->{dns_requests} = { };
+  $kernel->alias_set(ref($object) . "::" . $_[SESSION]->ID());
 }
 
 # When programs crash, the session may stop in a non-shutdown state.
@@ -208,8 +215,7 @@ sub _ka_stopped {
 }
 
 sub DESTROY {
-  my $self = shift;
-  $self->shutdown();
+  $_[0]->shutdown();
 }
 
 # Request to wake up.  This should only happen during the edge
@@ -434,8 +440,8 @@ sub allocate {
     "poco-client-keepalive"
   );
 
-  $poe_kernel->call("$self", ka_set_timeout     => $request);
-  $poe_kernel->call("$self", ka_resolve_request => $request);
+  $poe_kernel->call($self->[SF_ALIAS], ka_set_timeout     => $request);
+  $poe_kernel->call($self->[SF_ALIAS], ka_resolve_request => $request);
 
   return $request->[RQ_ID];
 }
@@ -455,7 +461,7 @@ sub deallocate {
   _free_req_id($request->[RQ_ID]);
 
   # Now pass the vetted request & its ID into our manager session.
-  $poe_kernel->call("$self", "ka_deallocate", $request, $req_id);
+  $poe_kernel->call($self->[SF_ALIAS], "ka_deallocate", $request, $req_id);
 }
 
 sub _ka_deallocate {
@@ -479,14 +485,14 @@ sub _ka_deallocate {
     "cancelling connection request"
   );
 
-  unless (exists $heap->{resolve}->{$request->[RQ_ADDRESS]}) {
+  unless (exists $heap->{dns_requests}{$request->[RQ_ADDRESS]}) {
     DEBUG_DEALLOCATE and warn(
       "deallocate cannot cancel dns -- no pending request"
     );
     return;
   }
 
-  $poe_kernel->call( "$self", ka_cancel_dns_response => $request );
+  $poe_kernel->call( $self->[SF_ALIAS], ka_cancel_dns_response => $request );
   return;
 }
 
@@ -496,7 +502,7 @@ sub _ka_cancel_dns_response {
   my $address = $request->[RQ_ADDRESS];
   DEBUG_DNS and warn "DNS: canceling request for $address\n";
 
-  my $requests = $heap->{resolve}{$address};
+  my $requests = $heap->{dns_requests}{$address};
 
   # Remove the resolver request for the address of this connection
   # request
@@ -514,7 +520,7 @@ sub _ka_cancel_dns_response {
   unless (@$requests) {
     DEBUG_DNS and warn "DNS: canceled all requests for $address";
     $self->[SF_RESOLVER]->cancel( $request->[RQ_RESOLVER_ID] );
-    delete $heap->{resolve}{$address};
+    delete $heap->{dns_requests}{$address};
   }
 
   # cancel our attempt to connect
@@ -733,7 +739,7 @@ sub free {
   croak "can't free() unallocated socket" unless defined $used;
 
   # Reclaim the socket.
-  $poe_kernel->call("$self", "ka_reclaim_socket", $used);
+  $poe_kernel->call($self->[SF_ALIAS], "ka_reclaim_socket", $used);
 
   # Avoid returning things by mistake.
   return;
@@ -765,7 +771,7 @@ sub _check_free_pool {
 
   # _check_free_pool() may be operating in another session, so we call
   # the correct one here.
-  $poe_kernel->call("$self", "ka_relinquish_socket", $next_socket);
+  $poe_kernel->call($self->[SF_ALIAS], "ka_relinquish_socket", $next_socket);
 
   $self->[SF_USED]{$next_socket} = [
     $next_socket,  # USED_SOCKET
@@ -877,7 +883,7 @@ sub _ka_keepalive_timeout {
 
 sub _ka_relinquish_socket {
   my ($kernel, $socket) = @_[KERNEL, ARG0];
-  $kernel->alarm_remove($_[OBJECT]->[SF_SOCKETS]{$socket}[SK_TIMER]);
+  $kernel->alarm_remove($_[OBJECT][SF_SOCKETS]{$socket}[SK_TIMER]);
   $kernel->select_read($socket, undef);
 }
 
@@ -887,7 +893,7 @@ sub _ka_relinquish_socket {
 sub shutdown {
   my $self = shift;
   return if $self->[SF_SHUTDOWN];
-  $poe_kernel->call("$self", "ka_shutdown");
+  $poe_kernel->call($self->[SF_ALIAS], "ka_shutdown");
 }
 
 sub _ka_shutdown {
@@ -912,18 +918,22 @@ sub _ka_shutdown {
   }
 
   # Stop any pending resolver requests.
-  foreach my $host (keys %{$heap->{resolve}}) {
+  foreach my $host (keys %{$heap->{dns_requests}}) {
     DEBUG and warn "SHT: Shutting down resolver requests for $host";
 
-    foreach my $request (@{$heap->{resolve}{$host}}) {
+    foreach my $request (@{$heap->{dns_requests}{$host}}) {
       $self->_shutdown_request($kernel, $request);
     }
 
     # Technically not needed since the resolver shutdown should do it.
-    $self->[SF_RESOLVER]->cancel( $heap->{resolve}->[0]->[RQ_RESOLVER_ID] );
+    # They all share the same host, so canceling the first should get
+    # them all.
+    $self->[SF_RESOLVER]->cancel(
+      $heap->{dns_requests}{$host}[0][RQ_RESOLVER_ID]
+    );
   }
 
-  $heap->{resolve} = { };
+  $heap->{dns_requests} = { };
 
   # Shut down the resolver.
   DEBUG and warn "SHT: Shutting down resolver";
@@ -938,7 +948,7 @@ sub _ka_shutdown {
   }
 
   # Finish keepalive's shutdown.
-  $kernel->alias_remove("$self");
+  $kernel->alias_remove($self->[SF_ALIAS]);
   $self->[SF_SHUTDOWN] = 1;
 
   return;
@@ -1003,24 +1013,24 @@ sub _ka_resolve_request {
   # TODO - Would require AF_INET6 support around the SocketFactory.
   if ((($host =~ tr[.][.]) == 3) and ip_is_ipv4($host)) {
     DEBUG_DNS and warn "DNS: $host is a dotted quad; skipping lookup";
-    $kernel->call("$self", ka_add_to_queue => $request);
+    $kernel->call($self->[SF_ALIAS], ka_add_to_queue => $request);
     return;
   }
 
   # It's already pending DNS resolution.  Combine this with previous.
-  if (exists $heap->{resolve}->{$host}) {
+  if (exists $heap->{dns_requests}{$host}) {
     DEBUG_DNS and warn "DNS: $host is piggybacking on a pending lookup.\n";
 
     # All requests for the same host share the same resolver ID.
     # TODO - Although it should probably be keyed on host:port.
-    $request->[RQ_RESOLVER_ID] = $heap->{resolve}->{$host}->[0]->[RQ_RESOLVER_ID];
+    $request->[RQ_RESOLVER_ID] = $heap->{dns_requests}{$host}[0][RQ_RESOLVER_ID];
 
-    push @{$heap->{resolve}->{$host}}, $request;
+    push @{$heap->{dns_requests}{$host}}, $request;
     return;
   }
 
   # New request.  Start lookup.
-  $heap->{resolve}->{$host} = [ $request ];
+  $heap->{dns_requests}{$host} = [ $request ];
 
   $request->[RQ_RESOLVER_ID] = $self->[SF_RESOLVER]->resolve(
     event   => 'ka_dns_response',
@@ -1041,7 +1051,7 @@ sub _ka_dns_response {
   return if $self->[SF_SHUTDOWN];
 
   my $request_address = $request->{host};
-  my $requests = delete $heap->{resolve}->{$request_address};
+  my $requests = delete $heap->{dns_requests}{$request_address};
 
   DEBUG_DNS and warn "DNS: got response for request address $request_address";
 
@@ -1128,7 +1138,7 @@ sub _ka_add_to_queue {
   # Wake the session up, and return nothing, signifying sound and fury
   # yet to come.
   DEBUG and warn "posting wakeup for $conn_key";
-  $poe_kernel->post("$self", "ka_wake_up");
+  $poe_kernel->post($self->[SF_ALIAS], "ka_wake_up");
   return;
 }
 
@@ -1227,7 +1237,7 @@ POE::Component::Client::Keepalive - manage connections, with keep-alive
 
 =head1 VERSION
 
-version 0.271
+version 0.272
 
 =head1 SYNOPSIS
 
@@ -1250,9 +1260,9 @@ version 0.271
   exit;
 
   sub start {
-    $_[HEAP]->{ka} = POE::Component::Client::Keepalive->new();
+    $_[HEAP]{ka} = POE::Component::Client::Keepalive->new();
 
-    $_[HEAP]->{ka}->allocate(
+    $_[HEAP]{ka}->allocate(
       scheme  => "http",
       addr    => "127.0.0.1",
       port    => 9999,
@@ -3,10 +3,7 @@
 # when it's destroyed.
 
 package POE::Component::Connection::Keepalive;
-{
-  $POE::Component::Connection::Keepalive::VERSION = '0.271';
-}
-
+$POE::Component::Connection::Keepalive::VERSION = '0.272';
 use warnings;
 use strict;
 
@@ -68,14 +65,16 @@ sub wheel {
 sub close {
   my $self = shift;
 
-  DEBUG and warn "closing $self";
+  DEBUG and warn "closing $self ($self->[CK_WHEEL]) ($self->[CK_SOCKET])";
   if (defined $self->wheel) {
     $self->wheel->shutdown_input();
     $self->wheel->shutdown_output();
     $self->[CK_WHEEL] = undef;
   }
 
-  DEBUG and warn "about to close potentially tied socket/ tied = ", tied(*{$self->[CK_SOCKET]}) ;
+  DEBUG and warn "about to close potentially tied socket/ tied = ", (
+    tied(*{$self->[CK_SOCKET]}) || 'no'
+  );
   close $self->[CK_SOCKET];
 
   my $is_tied = defined tied(*{$self->[CK_SOCKET]});
@@ -88,7 +87,7 @@ sub close {
 
   if (DEBUG) {
     if (defined(fileno($self->[CK_SOCKET]))) {
-      warn "*** BUG: fileno still defined! Is " . fileno($self->[CK_SOCKET]);
+      warn "*** BUG: fileno still defined: " . fileno($self->[CK_SOCKET]);
     }
   }
 }
@@ -103,7 +102,7 @@ POE::Component::Connection::Keepalive - a wheel wrapper around a kept-alive sock
 
 =head1 VERSION
 
-version 0.271
+version 0.272
 
 =head1 SYNOPSIS
 
@@ -5,26 +5,42 @@ use strict;
 
 use POE;
 use POE::Component::Server::TCP;
+use Socket qw(sockaddr_in);
 
 my %clients;
 my %servers;
+my $seq = 0;
 
 sub spawn {
   my ($class, $port) = @_;
 
-  my $alias = $servers{$port} = "server_$port";
+  my $alias = 'TestServer_' . ++$seq;
 
   POE::Component::Server::TCP->new(
     Alias              => $alias,
-    Port               => $port,
+    Port               => $port,   # Random one if 0.
     Address            => "127.0.0.1",
     ClientInput        => \&discard_client_input,
     ClientConnected    => \&register_client,
     ClientDisconnected => \&unregister_client,
+    Started            => sub {
+      # Switch $port to the port this server actually bound on.
+      my $listener_sockname = $_[HEAP]{listener}->getsockname();
+      if (defined $listener_sockname) {
+        ($port, undef) = sockaddr_in($listener_sockname);
+      }
+      else {
+        $port = undef;
+      }
+    },
     InlineStates       => {
       send_something   => \&internal_send_something,
     },
   );
+
+  $servers{$port} = $alias;
+
+  return $port;
 }
 
 sub register_client {
@@ -50,8 +66,8 @@ sub internal_send_something {
 }
 
 sub shutdown {
-  foreach my $session (values(%servers), keys(%clients)) {
-    $poe_kernel->post($session => "shutdown");
+  foreach my $alias (values(%servers), keys(%clients)) {
+    $poe_kernel->post($alias => "shutdown");
   }
 }
 
@@ -18,10 +18,7 @@ use POE::Component::Resolver;
 use Socket qw(AF_INET);
 
 use TestServer;
-
-# Random port.  Kludge until TestServer can report a port number.
-use constant PORT => int(rand(65535-2000)) + 2000;
-TestServer->spawn(PORT);
+my $server_port = TestServer->spawn(0);
 
 POE::Session->create(
   inline_states => {
@@ -42,7 +39,7 @@ sub start {
   $heap->{cm}->allocate(
     scheme  => "http",
     addr    => "localhost",
-    port    => PORT,
+    port    => $server_port,
     event   => "got_conn",
     context => "first",
   );
@@ -54,7 +51,16 @@ sub got_conn{
   # The delete() ensures only one copy of the connection exists.
   my $connection = delete $stuff->{connection};
   my $which = $stuff->{context};
-  ok(defined($connection), "$which request honored asynchronously");
+
+  if (defined $connection) {
+    pass "$which request honored asynchronously";
+  }
+  else {
+    fail(
+      "$which request $stuff->{function} error $stuff->{error_num}: " .
+      $stuff->{error_str}
+    );
+  }
 
   my $is_cached = $stuff->{from_cache};
   # Destroy the connection, freeing its socket.
@@ -65,13 +71,14 @@ sub got_conn{
     $heap->{cm}->allocate(
      scheme  => "http",
      addr    => "localhost",
-     port    => PORT,
+     port    => $server_port,
      event   => "got_conn",
      context => "second",
     );
   } elsif ($which eq 'second') {
     ok(defined $is_cached, "$which request from cache");
     TestServer->shutdown();
+		$heap->{cm}->shutdown();
   }
 
 }
@@ -18,14 +18,12 @@ use POE::Component::Client::Keepalive;
 use POE::Component::Resolver;
 use Socket qw(AF_INET);
 
-# Random port.  Kludge until TestServer can report a port number.
-use constant PORT => int(rand(65535-2000)) + 2000;
-use constant UNKNOWN_PORT => PORT+1;
 use TestServer;
 
 diag("This test may take a long time if your firewall blackholes connections.");
 
-TestServer->spawn(PORT);
+my $server_port  = TestServer->spawn(0);
+my $unknown_port = $server_port + 1;    # Kludge. Fingers crossed.
 
 POE::Session->create(
   inline_states => {
@@ -61,7 +59,7 @@ sub start {
     $heap->{cm}->allocate(
       scheme  => "http",
       addr    => "127.0.0.1",
-      port    => PORT,
+      port    => $server_port,
       event   => "got_first_conn",
       context => "first",
     );
@@ -71,7 +69,7 @@ sub start {
     $heap->{cm}->allocate(
       scheme  => "http",
       addr    => "127.0.0.1",
-      port    => PORT,
+      port    => $server_port,
       event   => "got_first_conn",
       context => "second",
     );
@@ -121,7 +119,7 @@ sub test_max_queue {
   $heap->{cm}->allocate(
     scheme  => "http",
     addr    => "127.0.0.1",
-    port    => PORT,
+    port    => $server_port,
     event   => "got_third_conn",
     context => "third",
   );
@@ -129,7 +127,7 @@ sub test_max_queue {
   $heap->{cm}->allocate(
     scheme  => "http",
     addr    => "127.0.0.1",
-    port    => UNKNOWN_PORT,
+    port    => $unknown_port,
     event   => "got_fourth_conn",
     context => "fourth",
   );
@@ -17,11 +17,8 @@ use POE::Component::Client::Keepalive;
 use POE::Component::Resolver;
 use Socket qw(AF_INET);
 
-# Random port.  Kludge until TestServer can report a port number.
-use constant PORT => int(rand(65535-2000)) + 2000;
 use TestServer;
-
-TestServer->spawn(PORT);
+my $server_port = TestServer->spawn(0);
 
 POE::Session->create(
   inline_states => {
@@ -57,7 +54,7 @@ sub start {
     $heap->{cm}->allocate(
       scheme  => "http",
       addr    => "localhost",
-      port    => PORT,
+      port    => $server_port,
       event   => "got_first_conn",
       context => "first",
     );
@@ -67,7 +64,7 @@ sub start {
     $heap->{cm}->allocate(
       scheme  => "http",
       addr    => "localhost",
-      port    => PORT,
+      port    => $server_port,
       event   => "got_first_conn",
       context => "second",
     );
@@ -79,7 +76,17 @@ sub got_first_conn {
 
   my $conn = $stuff->{connection};
   my $which = $stuff->{context};
-  ok(defined($conn), "$which connection established asynchronously");
+
+  if (defined $conn) {
+    pass "$which request honored asynchronously";
+  }
+  else {
+    fail(
+      "$which request $stuff->{function} error $stuff->{error_num}: " .
+      $stuff->{error_str}
+    );
+  }
+
   if ($which eq 'first') {
     ok(not (defined ($stuff->{from_cache})), "$which not from cache");
   } else {
@@ -94,7 +101,17 @@ sub got_third_conn {
 
   my $conn = $stuff->{connection};
   my $which = $stuff->{context};
-  ok(defined($conn), "$which connection established asynchronously");
+
+  if (defined $conn) {
+    pass "$which request honored asynchronously";
+  }
+  else {
+    fail(
+      "$which request $stuff->{function} error $stuff->{error_num}: " .
+      $stuff->{error_str}
+    );
+  }
+
   is($stuff->{from_cache}, 'immediate', "$which connection request honored from pool immediately");
 }
 
@@ -111,7 +128,7 @@ sub test_pool_alive {
   $heap->{cm}->allocate(
     scheme  => "http",
     addr    => "localhost",
-    port    => PORT,
+    port    => $server_port,
     event   => "got_third_conn",
     context => "third",
   );
@@ -119,7 +136,7 @@ sub test_pool_alive {
   $heap->{cm}->allocate(
     scheme  => "http",
     addr    => "localhost",
-    port    => PORT,
+    port    => $server_port,
     event   => "got_fourth_conn",
     context => "fourth",
   );
@@ -129,7 +146,17 @@ sub got_fourth_conn {
   my ($kernel, $heap, $stuff) = @_[KERNEL, HEAP, ARG0];
 
   my $conn = delete $stuff->{connection};
-  ok(defined($conn), "fourth connection established asynchronously");
+
+  if (defined $conn) {
+    pass "fourth request established asynchronously";
+  }
+  else {
+    fail(
+      "fourth request $stuff->{function} error $stuff->{error_num}: " .
+      $stuff->{error_str}
+    );
+  }
+
   is ($stuff->{from_cache}, 'deferred', "connection from pool");
 
   $conn = undef;
@@ -14,11 +14,8 @@ use POE::Component::Client::Keepalive;
 use POE::Component::Resolver;
 use Socket qw(AF_INET);
 
-# Random port.  Kludge until TestServer can report a port number.
-use constant PORT => int(rand(65535-2000)) + 2000;
 use TestServer;
-
-TestServer->spawn(PORT);
+my $server_port = TestServer->spawn(0);
 
 POE::Session->create(
   inline_states => {
@@ -49,7 +46,7 @@ sub start {
     $heap->{cm}->allocate(
       scheme  => "http",
       addr    => "localhost",
-      port    => PORT,
+      port    => $server_port,
       event   => "got_conn",
       context => "first",
     );
@@ -59,7 +56,7 @@ sub start {
     $heap->{cm}->allocate(
       scheme  => "http",
       addr    => "localhost",
-      port    => PORT,
+      port    => $server_port,
       event   => "got_conn",
       context => "second",
     );
@@ -100,7 +97,7 @@ sub test_alloc {
   $heap->{cm}->allocate(
     scheme  => "http",
     addr    => "localhost",
-    port    => PORT,
+    port    => $server_port,
     event   => "and_free",
     context => "third",
   );
@@ -112,7 +109,16 @@ sub and_free {
   my $conn  = delete $stuff->{connection};
   my $which = $stuff->{context};
 
-  ok(defined($conn), "$which connection created successfully");
+  if (defined $conn) {
+    pass "$which request honored asynchronously";
+  }
+  else {
+    fail(
+      "$which request $stuff->{function} error $stuff->{error_num}: " .
+      $stuff->{error_str}
+    );
+  }
+
   is(
     $stuff->{from_cache}, 'immediate',
     "third connection honored from the pool"
@@ -105,10 +105,7 @@ $cm->shutdown();
 ### Test the connection.
 
 use TestServer;
-
-# Random port.  Kludge until TestServer can report a port number.
-use constant PORT => int(rand(65535-2000)) + 2000;
-TestServer->spawn(PORT);
+my $server_port = TestServer->spawn(0);
 
 POE::Session->create(
   inline_states => {
@@ -120,7 +117,7 @@ POE::Session->create(
       $heap->{cm}->allocate(
         scheme  => "http",
         addr    => "localhost",
-        port    => PORT,
+        port    => $server_port,
         event   => "got_conn",
         context => "first",
       );
@@ -15,10 +15,7 @@ use POE::Component::Resolver;
 use Socket qw(AF_INET);
 
 use TestServer;
-
-# Random port.  Kludge until TestServer can report a port number.
-use constant PORT => int(rand(65535-2000)) + 2000;
-TestServer->spawn(PORT);
+my $server_port = TestServer->spawn(0);
 
 POE::Session->create(
   inline_states => {
@@ -46,7 +43,7 @@ sub start {
   $heap->{cm}->allocate(
     scheme  => "http",
     addr    => "localhost",
-    port    => PORT,
+    port    => $server_port,
     event   => "got_conn",
     context => "first",
   );
@@ -81,7 +78,7 @@ sub check_for_input {
   $heap->{cm}->allocate(
     scheme  => "http",
     addr    => "localhost",
-    port    => PORT,
+    port    => $server_port,
     event   => "got_conn2",
     context => "first",
   );
@@ -17,10 +17,7 @@ use POE::Component::Resolver;
 use Socket qw(AF_INET);
 
 use TestServer;
-
-# Random port.  Kludge until TestServer can report a port number.
-use constant PORT => int(rand(65535-2000)) + 2000;
-TestServer->spawn(PORT);
+my $server_port = TestServer->spawn(0);
 
 POE::Session->create(
   inline_states => {
@@ -47,7 +44,7 @@ sub start {
   $heap->{cm}->allocate(
     scheme  => "http",
     addr    => "localhost",
-    port    => PORT,
+    port    => $server_port,
     event   => "got_first_conn",
     context => "first",
   );
@@ -74,7 +71,7 @@ sub keepalive_over {
   $heap->{cm}->allocate(
     scheme  => "http",
     addr    => "localhost",
-    port    => PORT,
+    port    => $server_port,
     event   => "got_conn",
     context => "second",
   );
@@ -82,7 +79,7 @@ sub keepalive_over {
   $heap->{cm}->allocate(
     scheme  => "http",
     addr    => "localhost",
-    port    => PORT,
+    port    => $server_port,
     event   => "got_conn",
     context => "third",
   );
@@ -20,12 +20,8 @@ use Socket qw(AF_INET);
 
 use TestServer;
 
-# Random port.  Kludge until TestServer can report a port number.
-use constant PORT => int(rand(65535-2000)) + 2000;
-TestServer->spawn(PORT);
-
-use constant ANOTHER_PORT => PORT + 1;
-TestServer->spawn(ANOTHER_PORT);
+my $port_a = TestServer->spawn(0);
+my $port_b = TestServer->spawn(0);
 
 POE::Session->create(
   inline_states => {
@@ -52,7 +48,7 @@ sub start {
     $heap->{cm}->allocate(
       scheme  => "http",
       addr    => "localhost",
-      port    => PORT,
+      port    => $port_a,
       event   => "got_conn",
       context => "first",
     );
@@ -62,7 +58,7 @@ sub start {
     $heap->{cm}->allocate(
       scheme  => "http",
       addr    => "localhost",
-      port    => PORT,
+      port    => $port_a,
       event   => "got_conn",
       context => "second",
     );
@@ -70,12 +66,22 @@ sub start {
 }
 
 sub got_conn {
-  my ($heap, $stuff) = @_[HEAP, ARG0];
+  my ($heap, $response) = @_[HEAP, ARG0];
 
-  my $conn  = delete $stuff->{connection};
-  my $which = $stuff->{context};
-  ok(defined($conn), "$which connection established asynchronously");
-  ok(!defined($stuff->{from_cache}), "$which connection request deferred");
+  my $conn  = delete $response->{connection};
+  my $which = $response->{context};
+
+  if (defined $conn) {
+    pass "$which request established asynchronously";
+  }
+  else {
+    fail(
+      "$which request $response->{function} error $response->{error_num}: " .
+      $response->{error_str}
+    );
+  }
+
+  ok(!defined($response->{from_cache}), "$which connection request deferred");
 
   $conn = undef;
 
@@ -86,7 +92,7 @@ sub got_conn {
   $heap->{cm}->allocate(
     scheme  => "http",
     addr    => "localhost",
-    port    => PORT,
+    port    => $port_a,
     event   => "got_another_conn",
     context => "third",
   );
@@ -95,22 +101,22 @@ sub got_conn {
   $heap->{cm}->allocate(
     scheme  => "http",
     addr    => "localhost",
-    port    => ANOTHER_PORT,
+    port    => $port_b,
     event   => "got_another_conn",
     context => "fourth",
   );
 }
 
 sub got_another_conn {
-  my ($heap, $stuff) = @_[HEAP, ARG0];
+  my ($heap, $response) = @_[HEAP, ARG0];
 
-  # Deleting here to avoid a copy of the connection in %$stuff.
-  my $conn  = delete $stuff->{connection};
-  my $which = $stuff->{context};
+  # Deleting here to avoid a copy of the connection in %$response.
+  my $conn  = delete $response->{connection};
+  my $which = $response->{context};
 
   if ($which eq 'third') {
     is(
-      $stuff->{from_cache}, 'immediate',
+      $response->{from_cache}, 'immediate',
       "$which connection request honored from pool"
     );
     return;
@@ -118,10 +124,19 @@ sub got_another_conn {
 
   if ($which eq 'fourth') {
     ok(
-      !defined ($stuff->{from_cache}),
+      !defined ($response->{from_cache}),
       "$which connection request honored from pool"
     );
-    ok(defined($conn), "$which connection established asynchronously");
+
+    if (defined $conn) {
+      pass "$which request established asynchronously";
+    }
+    else {
+      fail(
+        "$which request $response->{function} error $response->{error_num}: " .
+        $response->{error_str}
+      );
+    }
 
     # Free the connection first.
     $conn = undef;
@@ -18,16 +18,13 @@ use POE::Component::Resolver;
 use Socket qw(AF_INET);
 
 use TestServer;
-
-# Random port.  Kludge until TestServer can report a port number.
-use constant PORT => int(rand(65535-2000)) + 2000;
-TestServer->spawn(PORT);
+my $server_port = TestServer->spawn(0);
 
 # Listen on a socket, but don't accept connections.
 use IO::Socket::INET;
 my $unaccepting_listener = IO::Socket::INET->new(
   LocalAddr => "127.0.0.1",
-  LocalPort => PORT + 1,
+  LocalPort => $server_port + 1,  # Cross fingers.
   Reuse     => "yes",
 ) or die $!;
 
@@ -56,7 +53,7 @@ sub start {
     $heap->{cm}->allocate(
       scheme  => "http",
       addr    => "127.0.0.1",
-      port    => PORT,
+      port    => $server_port,
       event   => "got_conn",
       context => "first",
     );
@@ -69,7 +66,7 @@ sub start {
     $heap->{cm}->allocate(
       scheme  => "http",
       addr    => "127.0.0.1",
-      port    => PORT+1,
+      port    => $server_port+1,
       event   => "got_conn",
       context => "second",
       timeout => 0.5,
@@ -17,10 +17,9 @@ use POE::Component::Resolver;
 use Socket qw(AF_INET);
 
 use TestServer;
+my $server_port = TestServer->spawn(0);
 
-# Random port.  Kludge until TestServer can report a port number.
-use constant PORT => int(rand(65535-2000)) + 2000;
-TestServer->spawn(PORT);
+my $test_server_use_count = 0;
 
 POE::Session->create(
   inline_states => {
@@ -51,11 +50,14 @@ sub start_with {
   $heap->{cm}->allocate(
     scheme  => "http",
     addr    => "localhost",
-    port    => PORT,
+    port    => $server_port,
     event   => "got_conn",
     context => "first",
   );
+
+  ++$test_server_use_count;
 }
+
 sub start_without {
   my $heap = $_[HEAP];
 
@@ -67,35 +69,56 @@ sub start_without {
   $heap->{cm}->allocate(
     scheme  => "http",
     addr    => "localhost",
-    port    => PORT,
+    port    => $server_port,
     event   => "got_conn",
     context => "second",
   );
+
+  ++$test_server_use_count;
 }
 
+# TODO - I think this callback is polymorphic (first vs. second)
+# bcause it has common code.  It's probably cleaner to implement two
+# separate callbacks and some helpers to handle their commonalities.
+
 sub got_conn{
-  my ($kernel, $heap, $stuff) = @_[KERNEL, HEAP, ARG0];
+  my ($kernel, $heap, $response) = @_[KERNEL, HEAP, ARG0];
 
   # The delete() ensures only one copy of the connection exists.
-  my $connection = delete $stuff->{connection};
-  my $which = $stuff->{context};
-  ok(defined($connection), "$which request honored asynchronously");
-  ok(not (defined ($stuff->{'from_cache'})), "$which request not from cache");
+  my $connection = delete $response->{connection};
+  my $which = $response->{context};
+
+  if (defined $connection) {
+    pass "$which request honored asynchronously";
+  }
+  else {
+    fail(
+      "$which request $response->{function} error $response->{error_num}: " .
+      $response->{error_str}
+    );
+  }
+
+  ok(
+    (not defined $response->{'from_cache'}),
+    "$which request not from cache"
+  );
 
   if ($which eq 'first') {
     ok(1, "$which request from internal resolver");
   } elsif ($which eq 'second') {
     ok(1, "$which request from external resolver");
-    # need this so we don't get trace output about our session having
-    # already died
-    $connection = undef;
-    # and this so we can terminate without having to go through the
-    # idle polling period
-    $heap->{cm}->shutdown;
-    # and this so we terminate at all
-    delete $heap->{cm};
-    TestServer->shutdown();
   }
+
+  TestServer->shutdown() unless --$test_server_use_count;
+
+  # need this so we don't get trace output about our session having
+  # already died
+  $connection = undef;
+  # and this so we can terminate without having to go through the
+  # idle polling period
+  $heap->{cm}->shutdown;
+  # and this so we terminate at all
+  delete $heap->{cm};
 }
 
 POE::Kernel->run();
@@ -16,11 +16,8 @@ use POE::Component::Client::Keepalive;
 use POE::Component::Resolver;
 use Socket qw(AF_INET);
 
-# Random port.  Kludge until TestServer can report a port number.
-use constant PORT => int(rand(65535-2000)) + 2000;
 use TestServer;
-
-TestServer->spawn(PORT);
+my $server_port = TestServer->spawn(0);
 
 POE::Session->create(
   inline_states => {
@@ -56,7 +53,7 @@ sub start {
     $heap->{cm}->allocate(
       scheme  => "http",
       addr    => "localhost",
-      port    => PORT,
+      port    => $server_port,
       event   => "got_first_conn",
       context => "first",
     );
@@ -66,7 +63,7 @@ sub start {
     $heap->{cm}->allocate(
       scheme  => "http",
       addr    => "localhost",
-      port    => PORT,
+      port    => $server_port,
       event   => "got_first_conn",
       context => "second",
     );
@@ -19,10 +19,7 @@ use POE::Component::Resolver;
 use Socket qw(AF_INET);
 
 use TestServer;
-
-# Random port.  Kludge until TestServer can report a port number.
-use constant PORT => int(rand(65535-2000)) + 2000;
-TestServer->spawn(PORT);
+my $server_port = TestServer->spawn(0);
 
 my $global_cm = POE::Component::Client::Keepalive->new(
   resolver => POE::Component::Resolver->new(af_order => [ AF_INET ]),
@@ -42,7 +39,7 @@ sub start {
   $global_cm->allocate(
     scheme  => "http",
     addr    => "127.0.0.1",
-    port    => PORT,
+    port    => $server_port,
     event   => "got_conn",
     context => "first",
   );
@@ -15,10 +15,7 @@ use POE::Component::Resolver;
 use Socket qw(AF_INET);
 
 use TestServer;
-
-# Random port.  Kludge until TestServer can report a port number.
-use constant PORT => int(rand(65535-2000)) + 2000;
-TestServer->spawn(PORT);
+my $server_port = TestServer->spawn(0);
 
 POE::Session->create(
   inline_states => {
@@ -46,7 +43,7 @@ sub start {
   $heap->{cm}->allocate(
     scheme  => "http",
     addr    => "localhost",
-    port    => PORT,
+    port    => $server_port,
     event   => "got_first_conn",
     context => "first",
   );
@@ -71,10 +68,10 @@ sub got_first_conn {
   $heap->{cm}->allocate(
     scheme => "http",
     addr => "localhost",
-    port => PORT,
+    port => $server_port,
     event => "got_second_conn",
     context => "second"
-  );  
+  );
 }
 
 
@@ -18,13 +18,8 @@ use POE::Component::Resolver;
 use Socket qw(AF_INET);
 
 use TestServer;
-
-# Random port.  Kludge until TestServer can report a port number.
-use constant PORT => int(rand(65535-2000)) + 2000;
-TestServer->spawn(PORT);
-
-use constant ANOTHER_PORT => PORT + 1;
-TestServer->spawn(ANOTHER_PORT);
+my $server_port  = TestServer->spawn(0);
+my $another_port = TestServer->spawn(0);
 
 POE::Session->create(
   inline_states => {
@@ -52,7 +47,7 @@ sub start {
     $heap->{cm}->allocate(
       scheme  => "http",
       addr    => "localhost",
-      port    => PORT,
+      port    => $server_port,
       event   => "got_conn",
       context => "first/$_",
     );
@@ -64,21 +59,30 @@ sub got_conn {
 
   my $conn  = delete $stuff->{connection};
   my $which = $stuff->{context};
-  ok(defined($conn), "$which connection established asynchronously");
+
+  if (defined $conn) {
+    pass "$which request established asynchronously";
+  }
+  else {
+    fail(
+      "$which request $stuff->{function} error $stuff->{error_num}: " .
+      $stuff->{error_str}
+    );
+  }
 
   $conn = undef;
   if (++$heap->{request_count} == 1) {
     $heap->{cm}->allocate(
       scheme => "http",
       addr => "localhost",
-      port => PORT,
+      port => $server_port,
       event => "got_conn",
       context => "second-a"
     );
     $heap->{cm}->allocate(
       scheme => "http",
       addr => "localhost",
-      port => ANOTHER_PORT,
+      port => $another_port,
       event => "got_conn",
       context => "second-b"
     );
@@ -7,15 +7,9 @@ BEGIN {
   }
 }
 
+# This file was automatically generated by Dist::Zilla::Plugin::PodCoverageTests.
 
-use Test::More;
-
-eval "use Test::Pod::Coverage 1.08";
-plan skip_all => "Test::Pod::Coverage 1.08 required for testing POD coverage"
-  if $@;
-
-eval "use Pod::Coverage::TrustPod";
-plan skip_all => "Pod::Coverage::TrustPod required for testing POD coverage"
-  if $@;
+use Test::Pod::Coverage 1.08;
+use Pod::Coverage::TrustPod;
 
 all_pod_coverage_ok({ coverage_class => 'Pod::Coverage::TrustPod' });
@@ -7,9 +7,8 @@ BEGIN {
   }
 }
 
+# This file was automatically generated by Dist::Zilla::Plugin::PodSyntaxTests.
 use Test::More;
-
-eval "use Test::Pod 1.41";
-plan skip_all => "Test::Pod 1.41 required for testing POD" if $@;
+use Test::Pod 1.41;
 
 all_pod_files_ok();