On Wed, Mar 21, 2001 at 11:09:13AM -0800, Rob Bloodgood wrote:
> In trying to make my app as long-lived and stable as possible, I've come up
> against a snag:
> In the even that my program fails, even when wrapped in an eval loop,
> when I try to re-start things, I find that there are existing sessions in
> memory, my previous incarnations of POE::Component::Server::TCP, which give
> me bind errors( # 98 in my linux system if UR interested). <sigh>
>
> It would be great if I could capture the session ID's somehow so that I
> could stop/deallocate/wait on them explicitly, before restarting.

The biggest problem here is that POE::Kernel wasn't designed to be
stopped and restarted.  It may be easier to wrap the program in a
shell script that checks its return value and restarts it if there was
a problem.

> POE::Component::Server::TCP->new
>   ( Port     => 30003,
>     Acceptor => sub {
>       my ($socket, $peer_addr, $peer_port) = @_[ARG0, ARG1, ARG2];
>       print "Server::TCP received a connection.\n" if DEBUG;
>       # spawn the server session
>       ServerSession->new($socket, $peer_addr, $peer_port);
>     },
>     Error    => sub {  # Optional.
>       my ($operation, $errnum, $errstr) = @_[ARG0, ARG1, ARG2];
>       print "Server::TCP detected $operation error $errnum: $errstr\n"
>         if $errnum;
>       $::try++, die "\n" if $errnum == 98;
>     },
>   );

Maybe you don't need to die there.  Here's an off-the-cuff
"meta-server" that respawns a server whenever it receives a
'new_server' event.  The server, created within the 'new_server' event
handler, posts the meta-server a 'new_server' event whenever it dies
with error 98.

The one undocumented bit is that the TCP server component holds its
socketfactory wheel in $_[HEAP]->{listener}.  You'll need to delete
that for the component to shut its listening socket down.  Client::TCP
in POE 0.1207 or later will include a 'shutdown' event handler that
deletes $_[HEAP]->{listener} for you.

  POE::Session->create
    ( inline_states =>
      { _start => sub {
          $_[KERNEL]->alias_set( 'meta_server' );
          $_[KERNEL]->yield( 'new_server' );
        },
        new_server => sub {
          POE::Component::Server::TCP->new
            ( ...,
              Error => sub {
                my ($operation, $errnum, $errstr) = @_[ARG0, ARG1, ARG2];

                # Shut down the TCP server component.
                if ($POE::VERSION < 0.1207) {
                  delete $_[HEAP]->{listener};     # undocumented
                }
                else {
                  $_[KERNEL]->yield( 'shutdown' ); # documented after 0.1206
                }

                # Start a new TCP server component.  This probably
                # should go last, since it allows the 'shutdown' event
                # to be dispatched before 'new_server' starts a new
                # server.
                $_[KERNEL]->post( meta_server => 'new_server' )
                  if $errnum == 98;
              },
            );
        },
      }
    );

I've also added an Alias parameter for Server::TCP so they can be shut
down from outside themselves.  This will appear in 0.1207 or later.
>From the new documentation:

  =item Alias

  Alias is an optional name by which this server may be referenced.
  It's used to pass events to a TCP server from other sessions.

    Alias => 'chargen'

  Later on, the 'chargen' service can be shut down with:

    $kernel->post( chargen => 'shutdown' );


-- Rocco Caputo / [EMAIL PROTECTED] / poe.perl.org / poe.sourceforge.net

Reply via email to