Please report new issues athttps://github.com/DOCGroup
Opening an SSL connection to an unreachable endpoint leads to a timeout. But the used TCP socket remains unclosed and its handle leaks. Within programs running for a long time periodical connection retries make socket resources to run out. The following test code shows the problem: #include <ace/SSL/SSL_SOCK_Stream.h> #include <ace/Connector.h> #include <ace/SSL/SSL_SOCK_Connector.h> #include <sstream> class ConnHandler : public ACE_Svc_Handler <ACE_SSL_SOCK_Stream, ACE_MT_SYNCH> { public: ConnHandler() { printf("ConnHandler constructor\n"); } virtual ~ConnHandler() { printf("ConnHandler destructor\n"); } virtual int open(void * = NULL) { printf("ConnHandler open\n"); return -1; } virtual int handle_input(ACE_HANDLE = ACE_INVALID_HANDLE) { printf("ConnHandler handle_input\n"); return 0; } /** * Perform termination activities on the SVC_HANDLER. The default * behavior is to close down the <peer_> (to avoid descriptor leaks) * and to <destroy> this object (to avoid memory leaks)! If you * don't want this behavior make sure you override this method... */ virtual int handle_close(ACE_HANDLE = ACE_INVALID_HANDLE, ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK) { printf("ConnHandler handle_close\n"); // For SSL peer() contains the SSL socket and peer().peer() contains the TCP socket. // ACE Handle Leak: // At connect timeout the SSL socket handle is invalid, the TCP socket handle isn't. // ACE_SSL_SOCK_STREAM::close() doesn't anything when its SSL handle is invalid. // See your code in ACE_Wrappers/ace/SSL/SSL_SOCK_Stream.inl in line 317: // 312 ACE_INLINE int // 313 ACE_SSL_SOCK_Stream::close (void) // 314 { // 315 ACE_TRACE ("ACE_SSL_SOCK_Stream::close"); // 316 // 317 if (this->ssl_ == 0 || this->get_handle () == ACE_INVALID_HANDLE) // 318 return 0; // SSL_SOCK_Stream was never opened. // ... // 352 } // So the TCP socket remains NOT closed and the handle leaks. // Here our workaround to prevent a handle leak: ACE_SOCK_Stream & TCP_Peer = this->peer().peer(); if(TCP_Peer.get_handle() != ACE_INVALID_HANDLE) { std::stringstream sstr; sstr << "Closing TCP socket with handle " << (int)TCP_Peer.get_handle(); printf("handle_close %s\n", sstr.str().c_str()); TCP_Peer.close(); } // From the default function handle_close() from Svc_Handler.cpp line 304: // ACE_Svc_Handler<PEER_STREAM, SYNCH_TRAITS>::handle_close (ACE_HANDLE,ACE_Reactor_Mask) this->destroy(); return 0; } virtual int svc() { printf("ConnHandler svc\n"); return 0; } }; int main(int , char ** ) { // Using ACE 6.1.4 ACE_Connector < ConnHandler, ACE_SSL_SOCK_Connector > cSockConnector; ConnHandler * pcConnHandler = new ConnHandler(); // Use a not reachable endpoint. const ACE_INET_Addr ConnectAddr("172.22.113.7:35000"); int iConnectReturn = cSockConnector.connect(pcConnHandler, ConnectAddr); if(iConnectReturn < 0) { int iErrno = errno; printf("connect failed: Errno=%d\n", iErrno); } else { printf("connect successful\n"); } return 0; }