I'm having a bit of an issue with something I encountered while unit testing my socket classes - each test basically creates a thread on which a server socket listens. From the main thread I connect a client to the server socket. I've found that after about 10-15 such tests I cannot create new threads - so I was wondering if I might have missed something clearing up resources (the pthread_create method returns with EAGAIN, which means insufficient resources). This only happens with ssl sockets when I connect a client, if I use normal sockets everything works well.

I have the following code, stripped of error handling for clarity (I've marked with * lines which are missing/different in the normal socket implementation versus the ssl socket one):

ClientSocket:

connect():
this->socket = BIO_new_ssl_connect(ssl_context); *
BIO_get_ssl(this->socket, &this->ssl); *
BIO_set_nbio(this->socket, NON_BLOCKING);

BIO_set_conn_hostname(this->socket, this->host);
BIO_set_conn_port(this->socket, port_str);
bool keep_connecting = true;

while (keep_connecting)
{
   if (BIO_do_connect(this->socket) > 0)
   {
        if (this->do_verify_handshake_result()) this->connected = true;
        keep_connecting = false;
   }
   else if (!BIO_should_retry(this->socket)) keep_connecting = false;
}
--

do_verify_handshake_result(): * (just returns true for normal sockets)
bool keep_trying = true;

while (keep_trying)
{
   if (BIO_do_handshake(this->socket) > 0)
   {
       if (SSL_get_verify_result(this->ssl) == X509_V_OK) result = true;
       keep_trying = false;
   }
   else if (!BIO_should_retry(this->socket)) keep_trying = false;
}
--

ServerSocket:
listen():
this->ssl_socket = BIO_new_ssl(ssl_context, SERVER_CONNECTION); *
BIO_get_ssl(this->ssl_socket, &this->ssl); *
this->accept_socket = BIO_new_accept(port_str);
BIO_set_accept_bios(this->accept_socket, this->ssl_socket); *
BIO_set_nbio(this->accept_socket, NON_BLOCKING);
BIO_do_accept(this->accept_socket);

while (!this->shutdown_requested)
{
   if (BIO_do_accept(this->accept_socket) > 0)
   {
ClientSocket *incoming_client= new_client_socket(BIO_pop(this->accept_socket));
           incoming_client->do_verify_handshake_result();
           connection_complete(incoming_client)
   }
}
--
connection_complete(): (this is just a test method)

delete incoming_client;
--
Test code:

typedef struct str_thdata
{
   int thread_no;
  ServerSocket *socket;
} thdata;

void *print_message_function ( void *ptr )
{
thdata *data = (thdata *) ptr; printf("Thread %d s\n", data->thread_no);fflush(stdout);
   data->socket->listen();
   return NULL;
}

int test()
{
for (int i = 0; i < 200; i++)
   {
       pthread_t thr;
       thdata data;
       data.thread_no = i;
ServerSocket *socket = SocketFactory::new_server_socket(SSL, TEST_PORT);
       data.socket = socket;

if (pthread_create (&thr, NULL, print_message_function, (void *) &data) != 0) printf("Warning, create did not work for thread #%d\n", i);fflush(stdout);
       else
       {
           Sleep(1000);
ClientSocket *client = SocketFactory::new_client_socket(SSL, (char *) "127.0.0.1", TEST_PORT);

           if (client->connect())
              client->disconnect();
delete client;

           socket->shutdown();
pthread_join(thr, NULL); }

       delete socket;
   }

}

If I use normal server&client sockets, all threads work as expected (can create 200). Also, if I use an SSL server, but with no client connecting to it (creating a server socket & thread and then closing them 200 times) - everything works as expected. If I connect an SSL client socket, no resources after 10-15 threads - I can get this to happen reliably. Sometimes I get a few error messages and then I can create threads again for a while.

Initially, I had SSL_MODE_AUTO_RETRY set on the server socket (left over from when the two classes were using blocking sockets) - removing it improved the situation a bit, but not by much (ie before I got thread creation errors on each run, now I get them about once for every two runs).

The disconnect/shutdown methods both for client and server just do "BIO_free_all(this->socket);", besides setting some bool variables such as connected/shutdown_requested. The destructors call disconnect/shutdown if sockets are not already closed.

Any ideas on what I'm doing wrong with this? I think I'm neglecting to release some resources, but I don't see what could those be - everything is closed before each new loop iteration. Setting a "Sleep()" right before the loop restarts did not help either.

Thanks in advance,

--
Laura
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           majord...@openssl.org

Reply via email to