Проблема с сокетом модуля apache/php
Я использую сервер Apache2.2 +PHP 5.2 под Debian Lenny 32bit. Я встроил в C "простое" расширение модуля php. Это расширение делает одну вещь: вызов через сокет небольшого "эхо-сервера" и ожидание результата (отправка / получение "A" с обеих сторон).
Находясь в модели prefork-mpm, я установил свой сокет в глобальную структуру PHP var. Так что глобально источник расширения звучит так:
В mymodule.h
ZEND_BEGIN_MODULE_GLOBALS(hello)
int socket;
ZEND_END_MODULE_GLOBALS(hello)
#ifdef ZTS
#define HELLO_G(v) TSRMG(hello_globals_id, zend_hello_globals *, v)
#else
#define HELLO_G(v) (hello_globals.v)
#endif
В mymodule.c
...
static int sock_create(char *address, int port, SA_IN *servaddr)
{
int s;
s = socket(AF_INET, SOCK_STREAM, 0);
if (!s)
return 0;
memset(servaddr, 0, sizeof(SA_IN));
servaddr->sin_family = AF_INET;
servaddr->sin_port = htons((unsigned short)port);
servaddr->sin_addr.s_addr = inet_addr(address);
return s;
}
int send_recv(int sock, char ch)
{
int r;
char tmp[2];
tmp[0]=ch;
tmp[1]=0;
r = send(sock, 'A', 1, 0);
if (r<=-1)
return -1;
r = recv(sock, tmp, 1, 0);
if (r<=-1)
return -2;
return (int) tmp[0];
}
PHP_FUNCTION(cmd_echo)
{
int item, r=0;
SA_IN addr;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &item)==FAILURE)
WRONG_PARAM_COUNT;
if (HELLO_G(sa)==0)
{
HELLO_G(sa) = sock_create("server_ip", 4500, &addr);
r = connect(HELLO_G(sa), (SA *) &addr, sizeof(SA));
send_recv(HELLO_G(sa), 'a');
RETURN_LONG(6);
}
else
{
send_recv(HELLO_G(sa), 'b'); // <---- trouble here, hangs...
RETURN_LONG(7);
}
RETURN_LONG(1);
}
Звучит идеально... Каждый раз, когда Apache разветвляет новый процесс, я создаю новое соединение (sa==0). Если через некоторое время Apache решает "повторно использовать" существующий процесс, мой сокет, который уже подключен (и Я в этом уверен) отправит данные на сервер без создания сокета. Просто действует как своего рода "пул сокетов"
Но тут приходит беда...
По неизвестной причине, в случае, когда Apache пытается повторно использовать открытый сокет, send_recv() зависает на команде send(). Конечно, сокет находится в режиме блокировки, но почему это поведение?
(Кстати, если я запускаю один и тот же код (без кода PHP, конечно) в исполняемый файл с несколькими send_recv, все работает отлично!)
Apache, кажется, блокирует сокет!??
Любая идея?