можно ли настроить "неразрыв" коннекта при умирании дочерних(pcntl_*) процессов?

StUV

Rotaredom
можно ли настроить "неразрыв" коннекта при умирании дочерних(pcntl_*) процессов?

собственно есть задача - распараллелить обработку данных.
но после умирания чайлда (созданного pcntl_fork) высвобождаются ресурсы.

есть ли возможность "запретить" чайлдам убивать коннект парента ?
или только "руками" рвать коннект в паренте перед форками, а в чайлдах открывать/закрывать отдельнве коннекты?

спасибо.

-~{}~ 13.07.07 11:45:

в общем, "ручной" способ ессно работает.

первый способ логически представляется невозможным, но... =)
 

MiksIr

miksir@home:~$
Гм....
PHP:
#!/usr/bin/php

<?

  $sock = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp'));
  socket_bind($sock, '127.0.0.1', 10000);
  socket_listen($sock);

  $conn = socket_accept($sock);
  print "1: $conn\n";

  $pid = pcntl_fork();

  if (!$pid) {
     // child
     print "2: $conn\n";
     exit;
  }

  pcntl_waitpid($pid, $status);

  print "3: $conn\n";

  socket_close ($conn);
  socket_close ($sock);

?>
Результат:
1: Resource id #5
2: Resource id #5
3: Resource id #5

Или я что-то не понял?

-~{}~ 13.07.07 16:17:

А, я понял, я тормоз - на название форума не посмотрел ;)
Речь о коннектах в базу? ;)

-~{}~ 13.07.07 16:22:

Под рукой есть постгрес
PHP:
#!/usr/bin/php

<?

  $link =  pg_connect("******", PGSQL_CONNECT_FORCE_NEW);

  print "1: $link\n";

  $pid = pcntl_fork();

  if (!$pid) {
     // child
     print "2: $link\n";
     exit;
  }

  pcntl_waitpid($pid, $status);

  print "3: $link\n";

  if (pg_connection_status($link) == PGSQL_CONNECTION_OK)
    print "ok\n";

?>
1: Resource id #4
2: Resource id #4
3: Resource id #4
ok
 

StUV

Rotaredom
в том то и вопрос - есть ли аналог для oci ?..

c коннектами парент/чайлд я разобрался
но, теперь та же фигня в параллельных чайлдах
в каждом открывается коннект, который при закрытии валит соединения остальных чайлдов
 

MiksIr

miksir@home:~$
php.net:
Замечание: oci_connect() не устанавливает соединение повторно, если соединение с такими параметрами (логин, пароль, имя сервера) уже было установлено. Вместо этого, oci_connect() вернет идентификатор уже открытого соединения. Это означает, что вам не следует использовать oci_connect() для разделения нескольких транзакций. Если вы уверены, что хотите установить соединение с теми же параметрами заново, то вам следует использовать oci_new_connect().
Т.е. или делай в детях new_connect или открывай коннект в родителе и юзай его в детях не закрывая (правда я хз как это будет работать при пересечениях... т.е. делается ли на дб сокет какая-нить блокировка между стадиями "послать запрос - получить ответ"... если нет, можно делать самому руками через какие-нибудь семафоры, шаренную память и т.п.)
 

StUV

Rotaredom
уже =)

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

если кто сталкивался с подобным - как вопрос решался ?

вижу несколько путей
- шаред мемори - не пробовал, так как мне это все-равно не доступно

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

- повесить на один коннект демон/шлюз и слать на него запросы

- ....

буду рад любым мыслям по этому поводу =)

-~{}~ 13.07.07 18:21:

открывай коннект в родителе и юзай его в детях не закрывая
дети падая рвут коннект при освобождении ресурсов без явного oci_close
 

MiksIr

miksir@home:~$
> дети падая рвут коннект при освобождении ресурсов без явного oci_close
Это оооочень странно. Проверьте... хотя бы моим примером, заменив вызовы постгрес на оракл.

> повесить на один коннект демон/шлюз и слать на него запросы
Это, имхо, красивое решение. Причем, наверняка даже есть такие готовые демоны, которые держут пул открытых соединений с ДБ сервером, принимают коннекты от клиентов и проксируют их в свободные из пула. Токда удастца избежать тормозов на oci_new_connect.
 

StUV

Rotaredom
Это оооочень странно.
но факт

Проверьте... хотя бы моим примером, заменив вызовы постгрес на оракл.
даже если в pg и все ОК, то мне от этого не легче - мне нужен оракл ;)

про демон+пул я тоже думал
но это сейчас слишком затратно по времени реализации
возможно придется идти в сторону кеширования части операций и отказаться от распараллеливания процессов - ессно, если получится найти ресурсы для кеширования или не удастся в ближайшее время решить проблему с общим коннектом для чайлдов

-~{}~ 14.07.07 11:33:

какой-то тупняк...
заменил

$this->_dbConnection = oci_connect(...);

на

$this->_dbConnection = & oci_connect(...);

и вроде бы "пока" работает

/me скрестил пальцы... =)
 

tony2001

TeaM PHPClub
>Это оооочень странно. Проверьте... хотя бы моим примером, заменив вызовы постгрес на оракл.
а чего тут странного?
чайлд - это копия родителя, с теми же ресурсами.
а поскольку ресурсы закрываются автоматом, то on shutdown чайлда всё закрывается на стороне сервера и клиента.

самый простой способ избежать этого - открывать коннекты после форка.
но это по сути то же самое, что и oci_new_connect() - у каждого чайлда будет свой собственный коннект.

>$this->_dbConnection = & oci_connect(...);

что вы там такое принимаете?
 

StUV

Rotaredom
что вы там такое принимаете?
вот и я ни черта не понял почему оно так...

-~{}~ 14.07.07 12:43:

самый простой способ избежать этого - открывать коннекты после форка
я так и сделал
но без этого "&" почему-то, когда один чайлд умирает и разрывает соединение - оно разрывается и у других параллельно работающих чайлдов
 

MiksIr

miksir@home:~$
> а поскольку ресурсы закрываются автоматом
Извините, кем закрывается, каким таким автоматом? Это в PHP встроено закрывать все без разбору? Дыг нет, я привел пример, что PHP этого не делает и сокеты не зыкрываются.
 

tony2001

TeaM PHPClub
>Извините, кем закрывается, каким таким автоматом?
http://lxr.php.net/source/php-src/ext/oci8/oci8.c#717

>Это в PHP встроено закрывать все без разбору?
Выговорился?
А теперь включи мозги вместо языка и подумай как еще это можно сделать.

Есть ресурсы (файловые дескрипторы, соединения). Если их не закрывать, то каждый скрипт будет открывать новые коннекты и в конце концов на сервере будут открыты тысячи, миллионы, миллиарды и т.п. коннектов.

Чайлд - это копия парента, чайлд не имеет ни малейшего понятия о том, что в воспалённом мозгу автора кода возникло желание не закрывать коннекты..

>Дыг нет, я привел пример, что PHP этого не делает и сокеты не зыкрываются.
Да что вы говорите?
А ты думал, что переменная типа resource указывающая на ресурс #4 магическим образом превратится в бабочку и улетит, как только коннект закроет другой процесс?
А оказывается, что нет. Переменная так и остаётся ресурсом, и даже внутренние данные остаются валидными.
Только на стороне сервера этот коннект уже закрыт - всё, поезд уехал.
 

MiksIr

miksir@home:~$
PHP:
#!/usr/bin/php

<?

  $sock = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp'));
  socket_bind($sock, '127.0.0.1', 10000);
  socket_listen($sock);

  $conn = socket_accept($sock);

  print "parent 1: $conn\n";

  $pid = pcntl_fork();

  if (!$pid) {
     // child
     print "child 1: $conn\n";
     socket_write($conn, "hi, i am a child\n");
     socket_close ($conn);
     print "child 2: $conn\n";
     exit;
  }

  pcntl_waitpid($pid, $status);

  print "parent 2: $conn\n";

  socket_write($conn, "hi, i am a parent\n");

  socket_close ($conn);

  socket_write($conn, "mmm?\n");

  socket_close ($sock);

?>
server ~ # telnet 127.0.0.1 10000
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
hi, i am a child
hi, i am a parent
Connection closed by foreign host.
parent 1: Resource id #5
child 1: Resource id #5
child 2: Resource id #5
parent 2: Resource id #5

Warning: socket_write(): 5 is not a valid Socket resource in /root/test2.php on line 32

Call Stack:
0.0005 55828 1. {main}() /root/test2.php:0
2.7970 56508 2. socket_write() /root/test2.php:32
-~{}~ 14.07.07 16:32:

В этом есть разница между close и shutdown.

-~{}~ 14.07.07 16:47:

Generally the difference between close() and shutdown() is: close() closes the socket id for the process but the connection is still opened if another process shares this socket id. The connection stays opened both for read and write, and sometimes this is very important. shutdown() breaks the connection for all processes sharing the socket id.

Хотя да, в драйверах базы данных происходит уничтожение линка при умирании скрипта. Но не надо говорить, что это логичное поведение для всех ресурсов.
 

tony2001

TeaM PHPClub
>В этом есть разница между close и shutdown.
в чем "в этом"?
в том, что чайлд закрыл сокет парента и парент не смог записать в закрытый сокет?
вы что принимаете? димедрол?
бросьте, это вредно для логики.
 

MiksIr

miksir@home:~$
Вы считаете, что оскорблениями что-то добъетесь? Или "положение обязывает", как у многих на этом форуме?

Парент _может_ записать в закрытый чайлдом по close сокет. Это во-первых - теория, и, во-вторых, показано мной на практике.
В случае с DB соединение с сервером шатдаунится.

2StUV - а Вы пробовали использовать в каждом чайлде персистент коннекты? В теории, они должны подхватывать уже установленные соединения, а значит и помочь избежать тормозов.
 

StUV

Rotaredom
Вы пробовали использовать в каждом чайлде персистент коннекты?
пробовал
то же самое

Чайлд - это копия парента, чайлд не имеет ни малейшего понятия о том, что в воспалённом мозгу автора кода возникло желание не закрывать коннекты..
tony2001
я уже выше написал, что с этой проблемой разобрался
проблема в том - почему чайлды открывающие параллельно коннекты с помощью oci_connect фактически получают одно и то же соединение и валят его друг другу ?
 
Сверху