Hi Arno
Once again many thanks for the quick reply. I have now implemented a working multithreaded test (server) application which uses both the TWSocket and the TSslWSocket in a non-blocking manner. The "regular" WSocket is used to accept incoming sessions, which are then carried on in a new client thread in which the sockethandle is "dupped" onto a TSslWSocket for further processing. I just have to be sure that I understood your reference to f_ERR_remove_state(unsigned ThreadID). Should I call this function just before the Thread's execute method returns, sending the threads ThreadID as param ? I have provided my sample code, for the benefit of others who had the same initial problem as me. If you can spare the time, I would be grateful if you could please verify that my use of the TSslWSocket is correct ? Excerpt of my sample code is listed below: Best regards Kurt ***Main Thread*** __fastcall TForm2::TForm2(TComponent* Owner) : TForm(Owner) { ... // Enable safe OpenSSL Multithreading before creating any ICS SSL sockets m_pSslDynamicLock = new TSslDynamicLock(NULL); m_pSslDynamicLock->Enabled = true; // Shared (thread-safe) SSL context m_pSslContext = new TSslContext(NULL); m_pSslContext->SslCertFile = "c:\\MyCertificate.pem"; m_pSslContext->SslPassPhrase = "password"; m_pSslContext->SslPrivKeyFile = "c:\\MyKey.pem"; m_pSslContext->SslCAFile = "c:\\root.cer"; m_pSslContext->SslCAPath = ""; m_pSslContext->SslVerifyPeer = false;// No client certificate verification // Listen for incoming connections m_pServerSocket = new TWSocket(NULL); m_pServerSocket->OnSessionAvailable = ServerSocketSessionAvailable; m_pServerSocket->Addr = "0.0.0.0"; m_pServerSocket->Port = "443"; m_pServerSocket->MultiThreaded = false;// We're in mainthread and should be fine. m_pServerSocket->Listen(); } //---------------------------------------------------------------------- ----- void __fastcall TForm2::ServerSocketSessionAvailable(TObject *Sender, WORD ErrCode) { try { // Accept incoming connection request unsigned int nSocketHandle = m_pServerSocket-> Accept(); // Do we have a valid Socket handle ? if( nSocketHandle > 0 && nSocketHandle < INVALID_SOCKET - 1 ) { // Thread initially created as suspended TSslClientThread* pClientThread = new TSslClientThread( m_hVclComponentCreationMutex, m_pSslContext, nSocketHandle ); pClientThread->OnTerminate = OnSslClientThreadTerminate; pClientThread->OnDebug = OnSslClientThreadDebug; // Add reference to thread, to keep track of session count m_SessionList.Add( pClientThread ); // Resume Thread pClientThread->Resume(); } } catch(Exception& ex) { DebugLog("TForm2::ServerSocketSessionAvailable, exception: " + ex.Message); } UpdateSessionCount(); } //---------------------------------------------------------------------- ----- void __fastcall TForm2::OnSslClientThreadTerminate(TObject* Sender) { if( Sender != NULL && Sender->ClassNameIs("TSslClientThread") ) { TSslClientThread* pThread = (TSslClientThread*)Sender; // Remove thread from list of active sessions int nIndex = m_SessionList.IndexOf( pThread ); // Valid index ? if( nIndex >= 0 && nIndex < m_SessionList.Count ) { m_SessionList.Remove( nIndex );// Only remove reference, not deleting obj. } UpdateSessionCount(); } } //---------------------------------------------------------------------- ----- ***Session Thread*** __fastcall TSslClientThread::TSslClientThread(HANDLE hMutex, TSslContext* pSslContext, unsigned int nSocketHandle ) : TThread(true)// create suspended { OnDebug = NULL; m_hVclComponentCreationMutex = hMutex; m_pSslContext = pSslContext; m_nSocketHandle = nSocketHandle; FreeOnTerminate = true; } //---------------------------------------------------------------------- ----- void __fastcall TSslClientThread::Execute() { // Init members // using a shared Mutex to avoid errors with components calling AllocateHwnd/DeallocateHwnd, which are not thread safe WaitForSingleObject( m_hVclComponentCreationMutex, INFINITE ); Init(); ReleaseMutex( m_hVclComponentCreationMutex ); // Loop until terminated ... while(!Terminated) { m_pClientSocket->ProcessMessages(); Sleep(1); } // Cleam up WaitForSingleObject( m_hVclComponentCreationMutex, INFINITE ); UnInit(); ReleaseMutex( m_hVclComponentCreationMutex ); } //---------------------------------------------------------------------- ----- bool TSslClientThread::Init(void) { bool bRetVal(false); try { m_pClientSocket = new TSslWSocket(NULL); m_pClientSocket->MultiThreaded = true;// Tell SslWSocket that it is run inside a seperate thread m_pClientSocket->SslContext = m_pSslContext;// According to Arno Garrels TSslContext should be threadsafe m_pClientSocket->SslMode = sslModeServer; m_pClientSocket->OnDataAvailable = ClientDataAvailable; m_pClientSocket->OnSessionClosed = ClientSessionClosed; m_pClientSocket->SslEnable = true; // Assign socket handle m_pClientSocket->Dup( m_nSocketHandle ); bRetVal = true; } catch(Exception& ex) { Fire_OnDebug("TSslClientThread::Init, exception: " + ex.Message); } return bRetVal; } //---------------------------------------------------------------------- ----- bool TSslClientThread::UnInit(void) { bool bRetVal(false); try { m_pClientSocket->Close(); while( m_pClientSocket->State != wsClosed ) { m_pClientSocket->ProcessMessages(); Sleep(1); } delete m_pClientSocket; m_pClientSocket = NULL; // DESCRIPTION // ERR_remove_state() frees the error queue associated with thread pid. // If pid == 0, the current thread will have its error queue removed. // Since error queue data structures are allocated automatically for // new threads, they must be freed when threads are terminated in order // to avoid memory leaks. f_ERR_remove_state(this->ThreadID); bRetVal = true; } catch(Exception& ex) { Fire_OnDebug("TSslClientThread::UnInit, exception: " + ex.Message); } return bRetVal; } //---------------------------------------------------------------------- ----- void __fastcall TSslClientThread::ClientDataAvailable(TObject* Sender, Word Error) { try { TSslWSocket* pSocket = (TSslWSocket*)Sender; AnsiString msg = pSocket->ReceiveStr(); } catch(Exception& ex) { Fire_OnDebug("TSslClientThread::ClientDataAvailable, exception: " + ex.Message); } } //---------------------------------------------------------------------- ----- void __fastcall TSslClientThread::ClientSessionClosed(TObject* Sender, Word Error) { try { // Terminate this thread ... Terminate(); } catch(Exception& ex) { Fire_OnDebug("TSslClientThread::ClientSessionClosed, exception: " + ex.Message); } } -- To unsubscribe or change your settings for TWSocket mailing list please goto http://lists.elists.org/cgi-bin/mailman/listinfo/twsocket Visit our website at http://www.overbyte.be