Hi all!
I am implementing an http server in c++ using the posix thread, but i am having a memory leak and i cannot find the reason.
I have already commented out the section that initializes the threads and i found out, the problem is when i initialize/run the threads.
In the threads i have already checked for every possible point to free the memory, but even inserting delete xxxx didnt work....
I am closing the socket, deleting its reference when not needed anymore, deleting every variable i am using to handle the data.... and so on...
Here is:
My main calls the pthread_create and passes as argument a pointer to a pthread_t. The main is responsible for this variable (creation and deleting).
Inside the thread i cast the argument (void*) to a (pthread_t *), i am using also two mutex (as global variables), accepting a connection (socket server), receiving data and responding, closing the connection.
The socket variable i am using as a pointer, cause i can delete after using it. Therefore, the leak is not related to the socket, i think...
But despite doing all of this when running the http server each new connection adds 8kb of memory to the used memory...
Each connection means a new thread....
I cannot find the bug, can anyone please help me?
Thanks in advance!
The code is down here:
#include <iostream>
#include "ServerSocket.h"
#include "SocketException.h"
#include <string>
#include <pthread.h>
#define MAX_CONNECTIONS 5
#define DEBUG
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; //to keep one thread for each connection
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER; //to change the variable nThreads
int nThreads = 0;
using namespace std;
// Create the socket
ServerSocket server ( 8080 );
/*
//-------creating
m_sock = socket ( AF_INET,
SOCK_STREAM,
0 );
if ( ! (m_sock != -1) )
return false;
// TIME_WAIT - argh
int on = 1;
if ( setsockopt ( m_sock, SOL_SOCKET, SO_REUSEADDR, ( const char* ) &on, sizeof ( on ) ) == -1 )
throw SocketException ( "Could not create server socket." );
//--------end creating
//--------start binding
m_addr.sin_family = AF_INET;
m_addr.sin_addr.s_addr = INADDR_ANY;
m_addr.sin_port = htons ( port );
int bind_return = ::bind ( m_sock,
( struct sockaddr * ) &m_addr,
sizeof ( m_addr ) );
if ( bind_return == -1 )
{
throw SocketException ( "Could not bind to port." );
}
//--------end binding
//--------start listening
int listen_return = ::listen ( m_sock, MAXCONNECTIONS );
if ( listen_return == -1 )
{
throw SocketException ( "Could not listen to socket." );
}
//--------end binding
*/
enum thread_status
{
INIT = 0
,RUNNING
,FINISHED
};
struct threads
{
pthread_t *thread;
thread_status status;
int id;
};
void *listen( void * ptr )
{
threads *stThread = (threads*) ptr; //casting
stThread->status = RUNNING; //changing status
//creating new socket
ServerSocket *new_sock = new ServerSocket();
/*
//do nothing
ServerSocket(){};
*/
try
{
pthread_mutex_lock( &mutex1 );
server.accept ( *new_sock );
/*
int addr_length = sizeof ( m_addr );
new_socket.m_sock = ::accept ( m_sock, ( sockaddr * ) &m_addr, ( socklen_t * ) &addr_length );
*/
pthread_mutex_unlock( &mutex1 );
try
{
std::string data;
(*new_sock) >> data; //receive data
data = "<html><body>The content of the body element is displayed in your browser.<img src=\"http://www.google.com.br/intl/en/images/about_logo.gif\">thread</body></html>";
(*new_sock) << data;//send data
new_sock->close(); //closing socket
/*
::close ( m_sock );
*/
}
catch ( SocketException& ex )
{
cout << strThread << "Exception was caught:" << ex.description() << "\nExiting.\n" << endl;
}
}
catch ( SocketException& e )
{
cout << strThread << "Exception was caught:" << e.description() << "\nExiting.\n" << endl;
}
pthread_mutex_lock( &mutex2 );
if( nThreads > 0 )
nThreads--;
pthread_mutex_unlock( &mutex2 );
if( new_sock )
delete new_sock;
stThread->status = FINISHED;
pthread_exit(NULL);
}
int main ( int argc, int argv[] )
{
threads stThreads[MAX_CONNECTIONS];
for( int i = 0; i < MAX_CONNECTIONS; i++ )
{
stThreads.status = INIT;
stThreads.id = i;
}
int threadsIndex = 0; // an index to the circular vector of stThreads
while( true )
{
if( nThreads < MAX_CONNECTIONS )
{
pthread_mutex_lock( &mutex2 );
nThreads++;
pthread_mutex_unlock( &mutex2 );
for( int i = 0; i < MAX_CONNECTIONS; i++ )
{
if( stThreads.status == FINISHED )
{
threadsIndex = i; //the thread to be created must be at the position 'i'
delete stThreads.thread; //cleaning the thread
stThreads.status = INIT; //changing its status
break;
}
}
stThreads[threadsIndex].thread = new pthread_t; //create the thread
pthread_create(stThreads[threadsIndex].thread, 0, listen, &stThreads[threadsIndex] );
threadsIndex++;
}
usleep(100);
}
pthread_exit(NULL);
}