Henrik,
You may recall a few weeks ago, I reported a problem I encountered when using
the mini-server to serve an HTTP document containing large amounts of image
content (50-60 gif icons). As I indicated, the current mini-server does not
yet correctly handle this situation. That is, is seems to open many more
sockets during the transmission of the document, than the maximum amount set
by the call to HTNet_setMaxSocket().
The reason this is so, I believe, is due to the following:
In HTNet.c the comments indicate that HTNet_newServer should return NO if
the number of active sockets exceed HTMaxActive sockets. Instead it always
returns YES. I've since changed this to return NO, when were out of sockets.
/* HTNet_newServer
** ---------------
** Create a new HTNet object as a new request to be handled. If we have
** more than HTMaxActive connections already then return NO.
** Returns YES if OK, else NO
*/
PUBLIC BOOL HTNet_newServer (HTRequest * request, SOCKET sockfd, char * access)
{
HTNet * me;
HTProtocol * protocol;
if (!request) return NO;
// added for testing JTD
if (PROT_TRACE) HTTrace("HTNet_newSvr %d active sockets\n",
HTList_count(HTNetActive));
/* Check if we can start the request, else return immediately */
if (HTList_count(HTNetActive) > HTMaxActive) {
if (PROT_TRACE) HTTrace("HTNet new... NO SOCKET AVAILABLE\n");
HTNetCall_execute(HTAfter, request, HT_RETRY);
/* return YES; */
return NO; // BUG FIX - JTD
}
... balance of code unchanged...
}
Also, HTNet_newServer() is called by server_handler() and is assumed to
never fail, but that is not the case. I have since changed this to check
the result of the call to HTNet_newServer and return an error if the server
cannot be created.
/* server_handler
** ---------------
** Is called if we get a read notification on server port
*/
PRIVATE int server_handler (SOCKET master, HTRequest * request, SockOps ops)
{
MiniServ * ms = (MiniServ *) HTRequest_context(request);
if (WWWTRACE) HTTrace("Accepting... socket %d\n", master);
if (ms->accept>0) ms->accept--;
if (ops == FD_READ) {
HTRequest * server = HTRequest_dup(request);
HTList_addObject(ms->active, server);
// HTNet_newServer(server, master, "http");
if (HTNet_newServer(server, master, "http")) // BUG FIX - JTD
return HT_OK;
}
return HT_ERROR;
}
So what has all this accomplished? Well not much, except that is does not crash
the machine when it runs out of sockets. Instead it exits the event loop and
terminates the appl, so my question is:
It appears when using persistant sockets, that incomming client requests can
allocate many more sockets than the server max sockets count permits and there
does not seem to be any mechanism in place currently to prevent this, or am
I missing something here?
If there is a known strategy to prevent this behavior I would be glad to
help write the code to implement. Your feedback is appreciated. sinc, -j
ps: my work mail server freesoft@ccia.com is currently out to lunch.
Please direct responses here or to jeff@macalot.com for now. Thanks