LINUX.ORG.RU

Perl, Mysql & fork - интересная проблемка


0

0

Интересная штука получается. Есть вот такой текст:

my $dbh = DBI->connect(...);
...
if (fork() == 0)
{
...
exit;
};

$dbh->commit;
$dbh->disconnect;

При fork все переменные дублируются в дочерний процесс. В том числе и $dbh. И при exit как я понял происходит автоматическое закрытие коннекта. После этого на $dbh->commit выскакивает "Broken pipe".

Так вот вопрос - можно-ли как-то замаскировать переменную $dbho, что-бы она не передавалась в дочерний процесс?

> можно-ли как-то замаскировать переменную $dbho,
> что-бы она не передавалась в дочерний процесс?

нет

я не знаю, можно ли решить вашу проблему средствами
DBI, т.к. мне мало что известно про последний. но вы
можете заменить вызов exit() на syscall(1,0), это
прямой вызов sys_exit(). тогда perl и libc даже не
узнают о завершении процесса.

idle ★★★★★
()
Ответ на: комментарий от idle

Это вариант. Однако я использую fork для того, что-бы вся память выделенная дочернем процессе по выходу из него освобождалась. Будет-ли она освобождаться при выходе через syscall?

UncleAndy ★★★
() автор топика
Ответ на: комментарий от UncleAndy

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

idle ★★★★★
()
Ответ на: комментарий от idle

Ну, это зависит от особенностей реализации fork в перле. :)
Если все так, как вы говорите - все нормально. :)

UncleAndy ★★★
() автор топика
Ответ на: комментарий от UncleAndy

> Ну, это зависит от особенностей реализации fork в перле. :)

это никак не может зависеть от особенностей реализации.
это завиисит от ядра, а оно вообще не знает, на каком
языке написана программа, вызывающая fork() или exit().

после вызова exit() любым способом ядро почистит все
ресурсы процесса.

idle ★★★★★
()
Ответ на: комментарий от idle

В приципе, логично.

А вот еще вопрос - как из дочернего процесса в родительский можно передать значение одной целой переменной?

Пробовал через файлы и через mysql - скорость не устраивает.

UncleAndy ★★★
() автор топика
Ответ на: комментарий от UncleAndy

> Сделал через pipe, но скорость что-то не блещет. :(

и как вы ее меряли ? это, конечно, не shared mem,
но должно быть очень быстро, сравнимо с временем
переключения контекста

idle ★★★★★
()

не понял, что, в перле, форк нa mysql IPC::Shareable использует(?):




      $handle = IO::Socket::INET->new(Proto     => "tcp",
                                      PeerAddr  => $host,
                                      PeerPort  => $port) or die "can't connect to port $port on $host: $!";
      $handle->autoflush(1);
      print STDERR "[Connected to $host:$port]\n";
      #  print STDERR "$ra $dec\n";
      die "can't fork: $!" unless defined($kidpid = fork());

      if ($kidpid) { $line='';
        while (defined ($line = <$handle>)){
          do{print $line; last} if $line=~m'ok';
          do{print $line," ERROR: bad command from socket\n"; exit 0} if $line=~m'error';
        } $line=''; #print "Выход из парента\n";
        kill("TERM", $kidpid);
        waitpid($kidpid,0);
      } else {
        print "abs $hh$mm$ss $tzeloe_delta"."$mm1\n";
#        sleep 1;
        print $handle "abs $hh$mm$ss $tzeloe_delta"."$mm1\n";
#        print $handle "rel -1 -1\n";
        open F,">>/mnt/data/mnt/work/log_obzor.txt";
        print F "abs $hh$mm$ss $tzeloe_delta"."$mm1\n";
        close F; #print "Выход из чайлда\n";
        exit;
      }
      open F,">>/mnt/data/mnt/work/log_obzor.


это если я сюда $dbh вставлю, то оно будет одинаковым во 
всех дочках чтоли? о чем вы вообще???

vilfred ☆☆
()
Ответ на: комментарий от vilfred

Вот именно! Одинаковым. Т.е. это будет один коннект. И при вызове exit в любом и чайлдов этот $dbh автоматом закроет соединение. И во всех остальных чайлдах и в родителе $dbh уже работать не будет.

UncleAndy ★★★
() автор топика
Ответ на: комментарий от vilfred

vilfred:
> не понял, что, в перле, форк нa mysql IPC::Shareable использует(?):
> это если я сюда $dbh вставлю, то оно будет одинаковым во всех дочках чтоли?

при чем здесь IPC... и perl даже не при чем. наследуется socket после
fork(), а sql серверу все равно, откуда пришла команда закрыть сессию.

idle ★★★★★
()
Ответ на: комментарий от idle

Да, это верно.

Хотя, нашел в какой-то доке упоминание параметра DBD хэндла, который устанавливает закрывать-ли соединение при выходе. Но при тестировании он не помог. Пришлось остановиться на варианте syscall(1,0) вместо exit.

UncleAndy ★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.