Модераторы: ginnie, korob2001
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> fork daemon 
:(
    Опции темы
o6s
Дата 8.6.2009, 22:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 28
Регистрация: 28.8.2008

Репутация: нет
Всего: нет



Сейчас знакомлюсь с книгой Вильямс - Разработка сетевых программ на Perl.
Пытаюсь понять как это работает. Вообщем понимание есть но не совсем.
Собственно проблема такая. Взял пример из книжки.. Даже если не переделывать то всё равно работает не правильно.
Daemon.pm
Код

package Daemon;
use strict;
use vars qw(@EXPORT @ISA @EXPORT_OK $VERSION);

use POSIX qw(:signal_h setsid WNOHANG);
use Carp 'croak','cluck';
use Carp::Heavy;
use File::Basename;
use IO::File;
use Cwd;
use Sys::Syslog qw(:DEFAULT setlogsock);
#use LogFile;
require Exporter;

@EXPORT_OK = qw(init_server prepare_child kill_children 
                launch_child do_relaunch
                log_debug log_notice log_warn 
                log_die %CHILDREN);
@EXPORT = @EXPORT_OK;
@ISA = qw(Exporter);
$VERSION = '1.00';

use constant PIDPATH  => '/var/run';
use constant FACILITY => 'local0';
use vars qw(%CHILDREN);
my ($pid,$pidfile,$saved_dir,$CWD);

sub init_server {
  my ($user,$group);
  ($pidfile,$user,$group) = @_;
  $pidfile ||= getpidfilename();
  my $fh = open_pid_file($pidfile);
  become_daemon();
  print $fh $$;
  close $fh;
  init_log();
  change_privileges($user,$group) if defined $user && defined $group;
  return $pid = $$;
}

sub become_daemon {
  croak "Can't fork" unless defined (my $child = fork);
  exit 0 if $child;    # parent dies;
  POSIX::setsid();     # become session leader
  open(STDIN,"</dev/null");
  open(STDOUT,">/dev/null");
  open(STDERR,">&STDOUT");
  $CWD = getcwd;       # remember working directory
  chdir '/';           # change working directory
  umask(0);            # forget file mode creation mask
  $ENV{PATH} = '/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin';
  delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
  $SIG{CHLD} = \&reap_child;
}

sub change_privileges {
  my ($user,$group) = @_;
  my $uid = getpwnam($user)  or die "Can't get uid for $user\n";
  my $gid = getgrnam($group) or die "Can't get gid for $group\n";
  $) = "$gid $gid";
  $( = $gid;
  $> = $uid;   # change the effective UID (but not the real UID)
}

sub launch_child {
  my $callback = shift;
  my $home     = shift;
  my $signals = POSIX::SigSet->new(SIGINT,SIGCHLD,SIGTERM,SIGHUP);
  sigprocmask(SIG_BLOCK,$signals);  # block inconvenient signals
  log_die("Can't fork: $!") unless defined (my $child = fork());
  if ($child==0) {
    $CHILDREN{$child} = $callback || 1;
  } else {
    $SIG{HUP} = $SIG{INT} = $SIG{CHLD} = $SIG{TERM} = 'DEFAULT';
    prepare_child($home);
  }
  sigprocmask(SIG_UNBLOCK,$signals);  # unblock signals
  return $child;
}

sub prepare_child {
  my $home = shift;
  if ($home) {
    local($>,$<) = ($<,$>);   # become root again (briefly)
    chdir  $home || croak "chdir(): $!";
    chroot $home || croak "chroot(): $!";
  }
  $< = $>;  # set real UID to effective UID
}

sub reap_child {
  while ( (my $child = waitpid(-1,WNOHANG)) > 0) {
    $CHILDREN{$child}->($child) if ref $CHILDREN{$child} eq 'CODE';
    delete $CHILDREN{$child};
  }
}

sub kill_children {
  kill TERM => keys %CHILDREN;
  # wait until all the children die
  sleep while %CHILDREN;
}

sub do_relaunch {
  $> = $<;  # regain privileges
  chdir $1 if $CWD =~ m!([./a-zA-z0-9_-]+)!;
  croak "bad program name" unless $0 =~ m!([./a-zA-z0-9_-]+)!;
  my $program = $1;
  my $port = $1 if $ARGV[0] =~ /(\d+)/;
  unlink $pidfile;
  exec 'perl','-T',$program,$port or croak "Couldn't exec: $!";
}

sub init_log {
  setlogsock('unix');
  my $basename = basename($0);
  openlog($basename,'pid',FACILITY);
  $SIG{__WARN__} = \&log_warn;
  $SIG{__DIE__}  = \&log_die;
}

sub log_debug  { syslog('debug',_msg(@_))  }
sub log_notice { syslog('notice',_msg(@_)) }
sub log_warn   { syslog('warning',_msg(@_))   }
sub log_die {
  syslog('crit',_msg(@_)) unless $^S;
  die @_;
}
sub _msg {
  my $msg = join('',@_) || "Something's wrong";
  my ($pack,$filename,$line) = caller(1);
  $msg .= " at $filename line $line\n" unless $msg =~ /\n$/;
  $msg;
}

sub getpidfilename {
  my $basename = basename($0,'.pl');
  return PIDPATH . "/$basename.pid";
}

sub open_pid_file {
  my $file = shift;
  if (-e $file) {  # oops.  pid file already exists
    my $fh = IO::File->new($file) || return;
    my $pid = <$fh>;
    croak "Invalid PID file" unless $pid =~ /^(\d+)$/;
    croak "Server already running with PID $1" if kill 0 => $1;
    cluck "Removing PID file for defunct server process $pid.\n";
    croak"Can't unlink PID file $file" unless -w $file && unlink $file;
  }
  return IO::File->new($file,O_WRONLY|O_CREAT|O_EXCL,0644)
    or die "Can't create $file: $!\n";
}

END { 
  $> = $<;  # regain privileges
  unlink $pidfile if defined $pid and $$ == $pid 
}

1;
__END__



Script.pl

Код

#!/usr/bin/perl
# file: eliza_hup.pl
# Figure 14.6:  Psychotherapist server that responds to HUP signal

use strict;
use lib '.';
use Chatbot::Eliza;
use IO::Socket;
use Daemon;

use constant PORT      => 1002;
use constant PIDFILE   => '/var/run/exchange.pid';
use constant USER      => 'nobody';
use constant GROUP     => 'nogroup';
use constant EXCHANGE => '/home/o6s/scripts/perl/daemon';
#init_log('/home/o6s/scripts/daemon/log.log') or die "can't open logfile\n";
# signal handler for child die events
$SIG{TERM} = $SIG{INT} = \&do_term;
$SIG{HUP}  = \&do_hup;

my $port = $ARGV[0] || PORT;
my $listen_socket = IO::Socket::INET->new(LocalPort => $port,
                                          Listen    => 20,
                                          Proto     => 'tcp',
                                          Reuse     => 1);
die "Can't create a listening socket: $@" unless $listen_socket;
my $pid = init_server(PIDFILE,USER,GROUP,$port);
log_notice "Server accepting connections on port $port\n";

while (my $connection = $listen_socket->accept) {
  my $host = $connection->peerhost;
  my $child = launch_child(undef,EXCHANGE);
  if ($child == 0) {
    $listen_socket->close;
    log_notice("Accepting a connection from $host\n");
    interact($connection);
    log_notice("Connection from $host finished\n");
    exit 0;
  }
  $connection->close;
}

sub interact {
  my $sock = shift;
  STDIN->fdopen($sock,"r")  or die "Can't reopen STDIN: $!";
  STDOUT->fdopen($sock,"w") or die "Can't reopen STDOUT: $!";
  STDERR->fdopen($sock,"w") or die "Can't reopen STDERR: $!";
  $| = 1;
che-nit' delaem );
}

sub do_term {
  log_notice("TERM signal received, terminating children...\n");
  kill_children();
  exit 0;
}

sub do_hup {
  log_notice("HUP signal received, reinitializing...\n");
  log_notice("Closing listen socket...\n");
  close $listen_socket;
  log_notice("Terminating children...\n");
  kill_children;
  log_notice("Trying to relaunch...\n");
  do_relaunch();
  log_die("Relaunch failed. Died");
}

END { 
  log_notice("Server exiting normally\n") if $$ == $pid;
}




посмотрел на дебаг.. подумал.. нчего ценного в голову не приходит...

Вообщем в кратце.

my $pid = init_server(PIDFILE,USER,GROUP,$port);  выполняется отлично т.е. закрывется родительский процесс и порождается fork.

while (my $connection = $listen_socket->accept) { начинаем слушать соединение, тоже отлично работает.

my $child = launch_child(undef,EXCHANGE); рождается новый процесс который должен обработать tcp запрос и умереть.

 И всё вроде ок, после второго процесса помирает основной процесс..
Лог выглядит так

Код

Jun  8 22:53:09 script.pl[6858]: Server accepting connections on port 1002 
Jun  8 22:53:24 script.pl[6917]: Accepting a connection from 127.0.0.1 
Jun  8 22:56:00 script.pl[6917]: Connection from 127.0.0.1 finished 
Jun  8 22:56:18 script.pl[6858]: chdir(): No such file or directory script.pl line 33 
Jun  8 22:56:18 script.pl[7569]: Accepting a connection from 127.0.0.1 
Jun  8 22:56:18 script.pl[6858]: Server exiting normally 

ну и соответственно конец )
Уже сломал весть мозг, но так и не могу понять почему во второй раз не отрабатывает chdir..
Заранее спасибо.
PM MAIL   Вверх
sir_nuf_nuf
Дата 9.6.2009, 07:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 920
Регистрация: 6.1.2008

Репутация: нет
Всего: 31



Код

 my $child = launch_child(undef,EXCHANGE);
  if ($child == 0) {
    exit 0;
  }


Вот этот код ненадежен.
что возвращает launch_child в процессе потомке ? 0 ? Тогда потомок ваш и пишите "Server exit normaly"

P.S. вы должны понимать, что у родителя и потомка один и тот же код.


--------------------
user posted image
user posted image
PM MAIL Jabber   Вверх
o6s
Дата 9.6.2009, 20:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 28
Регистрация: 28.8.2008

Репутация: нет
Всего: нет



Я имел ввиду не совсем это, но смысл вашего замечания понятен. 
Сейчас попробую кое-что переделать и посмотрю что из этого получится.
Спасибо за помощь.

Это сообщение отредактировал(а) o6s - 9.6.2009, 20:04
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Perl: Системное программирование"
korob2001
sharq
  • В этом разделе обсуждаются вопросы относящиеся только к системному программированию на Perl
  • Если ваш вопрос не относится к системному или CGI программированию, задавайте его в общем разделе
  • Если ваш вопрос относится к CGI программированию, задавайте его здесь
  • Интерпретатор Perl можно скачать здесь ActiveState, O'REILLY, The source for Perl
  • Справочное руководство "Установка perl-модулей", можно скачать здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Perl: Системное программирование | Следующая тема »


 




[ Время генерации скрипта: 0.0435 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.