Как отключить Net :: LDAP :: Server - PullRequest
0 голосов
/ 06 сентября 2018

У меня есть сервер Perl LDAP, который основан на использовании Net::LDAP::Server модуль. Чтобы он работал как сервис в Linux, я использую Net::Server::PreForkSimple библиотека.

Пока все работает нормально, но когда я закрываю службу, дочерние процессы не закрываются.

Как правильно закрыть все процессы?

Когда я посылаю сигнал SIGTERM, вызывается метод server_close, но больше ничего не происходит. С этого момента прерванные дети больше не перезапускаются, но дети, ожидающие работы, не прерываются.

#!/usr/bin/perl

#chkconfig: 345 80 05
#description: LDAP Server for Innovaphone

use strict;
use warnings;

package Listener;

use Net::Server;
use base 'Net::Server::PreForkSimple';

my $continue = 1;

...

sub process_request {
    my $self = shift;

    my $in  = *STDIN{IO};
    my $out = *STDOUT{IO};

    my $sock         = $self->{server}->{client};
    my $peer_address = $sock->peerhost();
    my $peer_port    = $sock->peerport();
    logwarn( "Connection accepted from $peer_address : $peer_port" );

    my $handler = InnoLdapServer->new($sock);

    while ( 1 ) {
        my $finished = $handler->handle;
        return if $finished;
    }
}

...

sub server_close {
    logmsg( "Server close called" );
    $continue = 0;
}

# Start daemon
Proc::Daemon::Init();

my $pidfile = File::Pid->new({ file => "/var/run/inno-ldap.pid" });

if ( $pidfile->running() ) {
    die "Already running";
}

$pidfile->write();

open( STDOUT, '>', "$logpath/inno-ldap.$logName.log" ) or die "Can't open stdout log";
select( ( select( STDOUT ), $| = 1 )[0] );    # make the log file "hot" - turn off buffering

open( STDERR, '>', "$logpath/inno-ldap.$logName.error.log" ) or die "Can't open error log";
select( ( select( STDERR ), $| = 1 )[0] );    # make the log file "hot" - turn off buffering

while ( $continue ) {

    # package main;
    $roothandler = Listener->run(
        port          => [ 636, "389/tcp" ],
        proto         => "ssl",   # use ssl as the default
        ipv           => "*",     # bind both IPv4 and IPv6 interfaces
        user          => "daemon",
        group         => "daemon",
        SSL_key_file  => "/home/root/ssl_cert/server.pem",
        SSL_cert_file => "/home/root/ssl_cert/server.pem",
        max_servers   => 10,
        log_level     => 4
    );
}

$pidfile->remove();

1;

Ответы [ 2 ]

0 голосов
/ 12 сентября 2018

Показанный код не имеет отношения к самому Net::Server, т.е. его ::PreForkSimple расширение; сам сервер должен быть закрыт, если программа завершается сигналом. Мы не видим код вызова и то, как вы " закрыли службу ", кроме как по упомянутому сигналу.

Для этого есть server_close метод в Net::Server. Но метод с тем же именем, к которому относится вопрос, похоже, используется в вашем классе Listener, который, таким образом, переопределяет метод (большого) родителя. Он только останавливает дальнейшую работу в дочерних процессах и не затрагивает сервер.

Так что, если это метод, вызываемый в обработчике сигналов, сервер никогда не отключается должным образом, и его существующие дочерние элементы остаются рядом. Вам необходимо вызвать server_close для объекта Net::Server или организовать собственный метод server_close для вызова родительского метода.

Документация Net::Server по Поток процесса объясняет

Во время фазы отключения сервера ($self->server_close) поток программы представляет собой следующее:

$self->close_children;  # if any  
$self->post_child_cleanup_hook;  
if (Restarting server) {
    $self->restart_close_hook();  
    $self->hup_server;  
}

$self->shutdown_sockets;  

$self->server_exit;

Если вызов по server_close для объекта Net::Server или для родительского объекта вашего Listener по какой-то причине не делает этого, попробуйте использовать отдельные методы, перечисленные в рабочем процессе.

Есть также сигналы, перечисленные в Net :: Server :: PreForkSimple"личность" в Завершение работы

Каждый из сотрудников Fork и PreFork поддерживает постепенное отключение с помощью сигнала QUIT. Когда получено сообщение QUIT, родитель подает сигнал детям и затем ждет их выхода.

и затем под Hot Deploy

Начиная с версии 2.000, сервер PreForkSimple принимает сигналы TTIN и TTOU. Когда получен TTIN, max_servers увеличивается на 1. Если получен сигнал TTOU, max_servers уменьшается на 1

Но я надеюсь, что это не нужно для его выключения, и уж точно не последнее.

0 голосов
/ 10 сентября 2018

Изменение цикла while (1) на while ($pidfile->running()) в process_request должно помочь. Установка $continue в ноль препятствует запуску новых прослушивателей, но, насколько я могу судить, подпрограмма process_request игнорирует эту переменную.

Конечно, для этого потребуется $pidfile, чтобы быть объявленным ранее, поскольку он не будет находиться в области видимости в process_request, так как он был объявлен (и назначен) после определения подпрограммы.

...