views:

60

answers:

3

A friend of mine is trying to fix up a custom http server in C++ written for windows to work in Linux. I tried to help him, but all I found seemed too obvious.

The app creates a thread for every time a request comes in. The thread serves the request and ends. After some number of requests (something over 300) new threads are not created anymore.

All I found is that there is a limit of threads that can be created. But it looks like finished threads are still there. Is that a problem with the code or do the thread handlers never get released?

This is a bit of code my friend extracted from the app:

pthread_t threadID;

StartingArgs *arg = new StartingArgs( &(this->cameraCounts), mapToSend,&(this->mapMutex), &(this->mutex), this->config );

if( pthread_create(&threadID, NULL, (this->startingRoutine) , (void*)arg ) != 0 )
    {
        ConsoleMessages::printDate();
        cout<< "snapshot maker: new thread creation failed\n";
    }

void *CameraCounter::startingRoutine( void *arg )
{
//stuff to do. removed for debugging

    delete realArgs;
    return NULL;
}
+2  A: 

You have to join the thread (pthread_join, also see wait(2)) after it finished or set the SIGCHILD handler to SIG_IGN.

smilingthax
He was joining them at some point, but it didn't seem to help. The threads were being joined back, but still wouldn't die.
naugtur
+7  A: 

Looks like you've got a bunch of "joinable" threads. They're waiting for someone to call pthread_join() on them. If you don't want to do that (to get the return value of the thread, for example), you can create the threads as 'detached':

pthread_t threadID;
pthread_attr_t attrib;

pthread_attr_init(&attrib); 
pthread_attr_setdetachstate(pthread_attr_t &attrib, PTHREAD_CREATE_DETACHED);

StartingArgs *arg = new StartingArgs( &(this->cameraCounts), mapToSend,&(this->mapMutex), &(this->mutex), this->config );

if( pthread_create(&threadID, &attrib, (this->startingRoutine) , (void*)arg ) != 0 )
{
        ConsoleMessages::printDate();
        cout<< "snapshot maker: new thread creation failed\n";
}

pthread_attr_destroy(&attrib);

void *CameraCounter::startingRoutine( void *arg )
{
//stuff to do. removed for debugging

    delete realArgs;
    return NULL;
}
Harper Shelby
Thanks. I remember seeing a version of the code that had a pthread_join call and it didn't help, but this looks nice.
naugtur
Joining can be useful, but in a setup like this one, it would cause serialization of the threads, which isn't what you want.
Harper Shelby
+1  A: 

I would recommend your friend to create a thread pool, and post work items to the thread pool. If there are available threads to service the work item, one thread is allocated, and given the work item. If no threads are available, the request should hang until a new thread is available. This way he can protect himself from draining too much system resources during a denial of service attack.

If it is unlikely that no more than 30 requests will be handled at any one time, then the thread pool should contain at the most 30 threads. The system resource allocation would then be predictable during a denial of service attack, and not depend on an arbitrary system limit.

Jörgen Sigvardsson
That's a wise thing as the server is expecting 3 concurrent connections at peak, but as I said he's just supporting code somebody else wrote and the focus of this question is on a quick fix. I suggested him to do what you wrote here already. It's those business reasons again...
naugtur