Я работаю на простом Mojolicious::Lite
сервере, который включает конечную точку веб-сокета.
Я хотел бы обработать некоторые сигналы завершения, чтобы корректно завершить соединения веб-сокета и избежать исключений в клиентах (a java application).
Я попытался определить свои обработчики сигналов так, как я привык на предыдущих серверах, используя HTTP::Daemon
. Проблема в том, что они, кажется, игнорируются. Возможно, переопределено в слое Mojolicious, я еще не нашел на нем никаких ссылок.
Я ожидаю увидеть мое сообщение о завершении, но этого не происходит
[Mon Mar 23 14:01:28 2020] [info] Listening at "http://*:3000"
Server available at http://127.0.0.1:3000
^C # <-- i want to see my signal received message here if type Ctrl-c
Я отправляю SIGINT
напрямую, введя Ctrl-C
, когда сервер находится на переднем плане в терминале, и я могу грациозно завершить работу сервера (например, при запуске cron или другим средним значением без отображения) с kill <pid>
.
In На некоторых предыдущих серверах я пытался быть довольно исчерпывающим, обрабатывая:
HUP
захваченный сигнал, используемый в настоящее время для перезагрузки конфигурации SIGINT
Ctrl- C SIGQUIT
Ctrl - \ SIGABRT
например, ненормальное завершение работы библиотеки SIGTERM
запрос внешнего завершения - "дружественный" kill
(противопоставление жестокому kill -9
TSTP
приостановить с помощью Ctrl-Z CONT
при выходе из Ctrl-Z с помощью fg
или bg
Все эти обработчики позволяют корректно завершить работу с чистящими ресурсами, обеспечивающими согласованность данных или перезагрузку конфигурации o • Модели данных после внешних изменений, в зависимости от программы и потребностей.
Я нашел пакет Mojo::IOLoop::Signal
, «Неблокирующий обработчик сигнала», но, похоже, это другое. Не так?
Вот мой упрощенный код (работает с простым perl ws_store_test.pl daemon
):
Файл ws_store_test.pl
# Automatically enables "strict", "warnings", "utf8" and Perl 5.10 features
use Mojolicious::Lite;
my $store = {};
my $ws_clients = {};
sub terminate_clients {
for my $peer (keys %$ws_clients){
$ws_clients->{$peer}->finish;
}
}
$SIG{INT} = sub {
say "SIGINT"; # to be sure to display something
app->log->info("SIGINT / CTRL-C received. Leaving...");
terminate_clients;
};
$SIG{TERM} = sub {
say "SIGTERM"; # to be sure to display something
app->log->info("SIGTERM - External termination request. Leaving...");
terminate_clients;
};
# this simulates a change on datamodel and notifies the clients
sub update_store {
my $t = localtime time;
$store->{last_time} = $t;
for my $peer (keys %$ws_clients){
app->log->debug(sprintf 'notify %s', $peer);
$ws_clients->{$peer}->send({ json => $store
});
}
}
# Route with placeholder - to test datamodel contents
get '/:foo' => sub {
my $c = shift;
my $foo = $c->param('foo');
$store->{$foo}++;
$c->render(text => "Hello from $foo." . (scalar keys %$store ? " already received " . join ', ', sort keys %$store : "") );
};
# websocket service with optional parameter
websocket '/ws/tickets/*id' => { id => undef } => sub {
my $ws = shift;
my $id = $ws->param('id');
my $peer = sprintf '%s', $ws->tx;
app->log->debug(sprintf 'Client connected: %s, id=%s', $peer, $id);
$ws_clients->{$peer} = $ws->tx;
$store->{$id} = {};
$ws->on( message => sub {
my ($c, $message) = @_;
app->log->debug(sprintf 'WS received %s from a client', $message);
});
$ws->on( finish => sub {
my ($c, $code, $reason) = @_;
app->log->debug(sprintf 'WS client disconnected: %s - %d - %s', $peer, $code, $reason);
delete $ws_clients->{$peer};
});
};
plugin Cron => ( '* * * * *' => \&update_store );
# Start the Mojolicious command system
app->start;