На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Внимательно изучите правила раздела перед созданием темы
0. ПРИЛАГАЙТЕ СВОИ СКРИПТЫ.
1. Прежде чем создать топик, используйте поиск. Возможно это уже обсуждалось.
2. В топике указывайте ОС, режим работы скрипта (CLI|CGI). Очень желателен вывод лог-файлов и того места, куда у вас назначен вывод данных (STDOUT|STDERR)
3. Помните: вы знаете что вы хотите, а форумчане - нет. Поэтому следуйте простому правилу: грамотный развернутый вопрос - грамотный развернутый ответ.
Модераторы: ANDLL
  
    > Многопоточный демон , при закрыии сокета процессы остаются в памяти
      Всем привет!

      Дали задачу написать многопоточный демон, который слушает какой-либо порт и приняв информацию на него работает с ней(а это суть рекурсивный поиск grep). Инфу полученную он отдает клиенту, а закончив работу с поиском должен освободить сокет от лишнего мусора, но не закрывать его и не умирать.

      Задачу необходимо по условию решить не обращаясь к "самостоятельным" модулям СПАНа, а сделать все ручками. И вот что я наваял:

      ExpandedWrap disabled
        #!/usr/bin/perl --
        # SERVER
         
         
        use strict;
        use threads;
        use IO::Socket;
        use Net::hostent;
        use POSIX;
         
         
        my $pid = fork;
        exit if $pid;  # ВЫКЛЮЧАЮ РОДИТЕЛЬСКИЙ ПРОЦЕСС, ЧТОБЫ РАБОТАЛ ДЕМОН
        die "Could not fork: $!\n" unless defined($pid);
         
        my $exit = 0;
         
        # ЗАКРЫВАЮ ДЕСКРИПТОРЫ
        for my $handle(*STDIN, *STDOUT, *STDERR) {
            open($handle, "+<", "/dev/null")
                or die "cant reopen $handle to /dev/null: $!\n";
        }
         
        POSIX::setsid() or die "Cant create a new session\n";
         
        my $die_flag = 0; # ЭТА ПЕРЕМЕННАЯ ОПРЕДЕЛЯЕТ СРОК ЖИЗНИ ДЕМОНА
        $SIG{INT} = $SIG{TERM} = $SIG{HUP} = \&signal_handler;
        $SIG{PIPE} = 'IGNORE';
         
        # САМ СЕРВЕР
        my $server = new IO::Socket::INET(LocalPort => 6666,
            TYPE => SOCK_STREAM,
            ReuseAddr => 1,
            Listen => 10
        ) or die $@;
         
         
        # РАБОТА, КОТОРУЮ ДОЛЖЕН ИСПОЛНЯТЬ СЕРВЕР                      
        sub handle_connection {
            my $socket = shift;
            my $output = shift || $socket;
         
            my $usage = "\nUsage:\nfind \'search string\' /where/to/find\n\n";
            print $output $usage;
            my ($where, $what);
            while (<$socket>) {
                if (/^find\s+\'(.+)\'\s+(.+)/) {
                    $what   = $1;
                    $where  = $2;
                }
                elsif (/^(help|\?)/) {
                     print $output $usage;
                }
                else {
                    print $output "Bad pattern!:\t$_\n$usage";
                    #last;
                }
                    
         
                while(my $line = `grep -r \'$what\' $where`) {
                    next if ($line =~ /grep:/);  # means 'permission denied'
                    print $output $line;
                    last if $exit;
                }
         
                print "Search done\n\n";
                $exit = 1;
                
                last if $exit;
            }
        }
         
        until ($die_flag) {
                # РАБОТА С ПОДКЛЮЧЕНИЯМИ К СОКЕТУ ДОЛЖНА ПО ИДЕЕ ЗАВЕРШИТЬСЯ КОРРЕКТНО, ЕСЛИ   $die_flag = 1
            while (my $socket = $server->accept) {  
                async(\&handle_connection, $socket)->detach; # В detach по идее сокет "очищается", но на самом деле нет,
            }
        }  
         
        sub signal_handler {
            $exit = 1;
            $die_flag = 1;
        }


      Подключившись nc localhost 6666, я вызываю команду find 'search string' /path/to , в итоге запускается grep. При досрочном закрытии клиента CTRL-C мой процесс grep остается в системе и растет в памяти, прямопропорционально количеству подключенных клиентов, демон тоже растет в объеме... >:(
      Сам думаю что конструкция
      ExpandedWrap disabled
        async(\&handle_connection, $socket)->detach;
      работает неверно, те detach почемуто не работает.

      Надеюсь, что расписал проблему понятно.... - при закрытии подключения со стороны клиента посредством CTRL_C - grep остается в списке рабочих процессов... ну и тп...
      Оч прошу помогите разобраться пож-ста!
        На мой взгляд вот здесь несчастье начинается:
        ExpandedWrap disabled
            while (<$socket>) {..


        В этом вайле нет работы с ресурсами. Т.е. я не увидел места, где осуществляется контроль работы.
          Цитата Nadz Goldman @
          На мой взгляд вот здесь несчастье начинается:
          ExpandedWrap disabled
              while (<$socket>) {..


          В этом вайле нет работы с ресурсами. Т.е. я не увидел места, где осуществляется контроль работы.

          Не совсем понятно, т.е. если я на удаленном хосте вышел из сессии соединения с помощью CTRL-C, то это можно как-то узнать на сервере? Ведь суть соединение оборвано - и есть информация, ресурс. Или как-то иначе?
            Да просто изначально не так подошел к проблеме.
            Да, конечно это можно узнать.

            Добавлено
            Примитивно, но просто -- форкаем процесс на поиск, форкаем на работу с клиентом, где ждем команды "стоп".
              Цитата Nadz Goldman @
              Добавлено
              Примитивно, но просто -- форкаем процесс на поиск, форкаем на работу с клиентом, где ждем команды "стоп".

              Добавил форк грепа, но греп в процессах после CTRL-C остается! :( Что сейчас не так?


              ExpandedWrap disabled
                ....
                my $pid2 = fork;
                exit if $pid2;
                die "Could not fork: $!\n" unless defined($pid2);
                 
                while (my $line = `grep -r \'$what\' $where`)  && defined($pid2)) {
                            next if ($line =~ /grep:/);  # means 'permission denied'
                            print $output $line;
                            last if $exit;
                }
                ...
                Да при чем здесь контрол-цэ?!!
                Контрол-цэ тогда обрабатывай в своей программе и при обнаружении таковой отсылай команду серверу "стоять!" и только после этого завершай программу-клиент.
                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                0 пользователей:


                Рейтинг@Mail.ru
                [ Script execution time: 0,0292 ]   [ 15 queries used ]   [ Generated: 27.04.24, 17:11 GMT ]