[prev in list] [next in list] [prev in thread] [next in thread] 

List:       apache-modules
Subject:    [apache-modules] strange poll/select problem in my apache module
From:       Christian Parpart <cparpart () surakware ! net>
Date:       2004-09-09 14:21:07
Message-ID: 200409091621.09807.cparpart () surakware ! net
[Download RAW message or body]


Hi all,

I know, this worked once, but since a few days, it doesn't, and I do *not* 
know what I've changed to get this happen.

Well, I have to care about early web client aborts, as well as backend server 
aborts while streaming data to the web client (I obviousely got from the 
backend server my module is connected to, too).

Well, the best way to achieve this, is, to poll on both.

At very first, I've to register a pre connection hook to catch the web clients 
file descriptor.

static void registerHooks(apr_pool_t *p) {
 ap_hook_pre_connection(getClientSocket, 0, 0, APR_HOOK_FIRST);
 // ...
}

int getClientSocket(conn_rec *conn, void *data) {
    apr_os_sock_get(&FClientSocket, reinterpret_cast<apr_socket_t *>(data));

    int optval = 1;
    setsockopt(FClientSocket, SOL_SOCKET, TCP_NODELAY, &optval,
        sizeof(optval));

    return OK;
}

Next, on a incoming connection, that belongs to us, I've to handle my stuff as 
usual *but* have to watch on early connection aborts on web client side, as 
well as on backend server side.

void TChatStreamer::streamPageBody() {
 pollfd pfds[2];
 pfds[0].fd = FWebClientSocket;
 pfds[0].events = POLLIN;
 pfds[1].fd = FBackendServerSocket;
 pfds[1].events = POLLIN;

 while (!FAborted) {
  int rv = poll(pfds, 2, 60 * 1000);
  if (rv > 0) {
   if (pfds[0].revents & POLLIN)
    FAborted = true;  /* early client abort */
   if (pfds[1].revents & POLLIN)
    handleEventFromServer(); /* got event from backend server */
  } else if (rv == -1) {
   FAborted = true;
  } else {
   handleTimeout();
  }
 }
 logoutClientFromBackendServer(); /* when we finished job, logout webclient */
}

void TChatStreamer::handleEventFromServer() {
 std::string input(readLineFd(FBackendServerSocket));
 if (input.empty())
  handleServerAbort();
 else
  handleEventFromServer(input);
}

void TChatStreamer::handleTimeout() {
 /* send some random HTML comment to web client in order to 
    keep connection alive */
}

Well done. This is just a rarely abstract code snippet, however, I intent to 
send all incoming events I get from the backend server to the web client, so, 
the apache module may be understood, to act as a proxy between. Important now 
is, that the web client, that also logged in to the backend server via the 
apache module, needs also to logout via this.
Of course, lots of user miss the logout button, and just close the webbrowser 
in order to sign, that they've done chatting, that is, they do *not* get any 
other events (e.g. chat messages) from the backend server via the apache 
module. So, the apache module needs to log them out automatically, at least, 
let them leave the channel they've currently joined. I repeat, this worked 
some day before, but obviousely, actually not. And I do not know why :(
Also, a problem would be, that the module would end into an infinite loop, 
when we cannot detect the early (web) client abort.

The problem now. The code above does *not* detect a client abort, poll() - 
previousely select() - does not return when the client aborts the connection. 
And even more *worse*, when the backend server disconnects its (apache) 
clients (e.g. via shutdown), the apache module's request handler just notices 
this, *BUT* also notices a client abort, that - of course - was not true.
This is strange, but why? What could have been the problem here?

So, when the backend server (int FBackendServerFd) closes connection, I get 
notified via poll() to have *two* closed connections, the backend server 
*AND* the webclient.
When I close the connection of the webbrowser (by just closing it), I get even 
nothing => the webserver's request handler runs into infinite loop => the 
backend server can't get notified about the real dead (web) client => we've 
lots of dead ppl in the chat I've to kick each day ;-)

I'd be really really happy, if anyone could give me any hint he has to fix 
this issue.

Regards,
Christian Parpart.

-- 
 15:56:10 up 16 days,  3:35,  0 users,  load average: 0.52, 0.43, 0.38

[Attachment #3 (application/pgp-signature)]

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic