apache/php module socket issue

393 views Asked by At

I'm running an Apache2.2 server+PHP 5.2 under Debian Lenny 32bit. I've built in C a "simple" php module extension. This extension is doing one thing: Calling, through a socket, a small "echo server" and waiting for the result (sending/receiving a 'A' on both side).

Being into a prefork-mpm model, I set my socket into global var PHP structure. So globally the extension source sounds like this :

In 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

In 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);
  }

Sounds perfect... Each time Apache forks a new process, I create a new connection (sa==0) If Apache, after a while, decides to "reuse" an existing process, my socket which is -already connected- (and I'm sure about that) will send datas to server without socket creation. Just acting like some kind of "socket pools"

But here comes the trouble...

For unknown reason, in the case where Apache tries to reuse an open socket, send_recv() hangs on send() command. Sure, the socket is in blocking mode, but why this behavior ?

(By the way, If I run the same code (without PHP code of course) into an executable with several send_recv, everything works perfectly !)

Apache seems to lock the socket !??

Any idea ?

0

There are 0 answers