Search code examples
perlmojolicious

How do I properly shut down a Mojolicious::Lite server?


In a Mojolicious::Lite app I have a route that I want to kill the server and redirect to another site. Here is the snippet.

my $me = $$;
get '/kill' => sub {
    my $self = shift;
    $self->res->code(301);
    $self->redirect_to('http://www.google.com');
    $self->app->log->debug("Goodbye, $name.");
  
    # I need this function to return so I delay the kill a little.
    system("(sleep 1; kill $me)&");
};

This code does what I want, but it doesn't feel right. I have tried $self->app->stop but that is not available.

Is there a proper technique I should be using to get access to the server?


Solution

  • Update 2021:

    This answer was referred to recently in an IRC discussion, so an update is warranted. The response below was a mechanism that I had used in a very specific case. While it may still be useful in rare cases, the more correct manner of stopping a service would be

    https://docs.mojolicious.org/Mojo/IOLoop#stop_gracefully or https://docs.mojolicious.org/Mojo/Server/Daemon#SIGNALS for a single-process server or https://docs.mojolicious.org/Mojo/Server/Prefork#MANAGER-SIGNALS for preforking


    Original:

    There are several ways to do this, of course.

    Probably the best, is to simply attach a finish handler to the transaction:

    #!/usr/bin/env perl
    
    use Mojolicious::Lite;
    
    get '/kill' => sub {
      my $c = shift;
      $c->redirect_to('http://google.com');
      $c->tx->on( finish => sub { exit } );
    };
    
    app->start;
    

    The method most like your example would be to setup a Mojo::IOLoop timer which would wait a few seconds and exit.

    #!/usr/bin/env perl
    
    use Mojolicious::Lite;
    use Mojo::IOLoop;
    
    get '/kill' => sub {
      my $c = shift;
      $c->redirect_to('http://google.com');
      my $loop = Mojo::IOLoop->singleton;
      $loop->timer( 1 => sub { exit } );
      $loop->start unless $loop->is_running; # portability
    };
    
    app->start;