diff -ruN mysql-5.1.39.orig/storage/ndb/include/util/SocketServer.hpp mysql-5.1.39/storage/ndb/include/util/SocketServer.hpp --- mysql-5.1.39.orig/storage/ndb/include/util/SocketServer.hpp 2009-10-13 15:43:50.000000000 +0200 +++ mysql-5.1.39/storage/ndb/include/util/SocketServer.hpp 2009-10-13 15:44:10.000000000 +0200 @@ -122,7 +122,7 @@ MutexVector m_services; unsigned m_maxSessions; - void doAccept(); + bool doAccept(); void checkSessionsImpl(); void startSession(SessionInstance &); diff -ruN mysql-5.1.39.orig/storage/ndb/src/common/util/SocketServer.cpp mysql-5.1.39/storage/ndb/src/common/util/SocketServer.cpp --- mysql-5.1.39.orig/storage/ndb/src/common/util/SocketServer.cpp 2009-10-13 15:39:46.000000000 +0200 +++ mysql-5.1.39/storage/ndb/src/common/util/SocketServer.cpp 2009-10-13 15:51:32.000000000 +0200 @@ -152,7 +152,7 @@ DBUG_RETURN(true); } -void +bool SocketServer::doAccept(){ fd_set readSet, exceptionSet; FD_ZERO(&readSet); @@ -177,7 +177,8 @@ if(FD_ISSET(si.m_socket, &readSet)){ NDB_SOCKET_TYPE childSock = accept(si.m_socket, 0, 0); if(childSock == NDB_INVALID_SOCKET){ - continue; + m_services.unlock(); + return false; } SessionInstance s; @@ -196,11 +197,14 @@ if(FD_ISSET(si.m_socket, &exceptionSet)){ DEBUG("socket in the exceptionSet"); - continue; + m_services.unlock(); + return false; } } } m_services.unlock(); + return true; + } extern "C" @@ -244,11 +248,16 @@ while(!m_stopThread){ m_session_mutex.lock(); checkSessionsImpl(); - if(m_sessions.size() < m_maxSessions){ - m_session_mutex.unlock(); - doAccept(); - } else { - m_session_mutex.unlock(); + m_session_mutex.unlock(); + + if(m_sessions.size() >= m_maxSessions){ + // Don't accept more connections yet + NdbSleep_MilliSleep(200); + continue; + } + + if (!doAccept()){ + // accept failed, step back NdbSleep_MilliSleep(200); } } diff -ruN mysql-5.1.39.orig/storage/ndb/test/ndbapi/testMgm.cpp mysql-5.1.39/storage/ndb/test/ndbapi/testMgm.cpp --- mysql-5.1.39.orig/storage/ndb/test/ndbapi/testMgm.cpp 2009-10-13 15:39:43.000000000 +0200 +++ mysql-5.1.39/storage/ndb/test/ndbapi/testMgm.cpp 2009-10-13 16:29:28.000000000 +0200 @@ -787,6 +787,59 @@ return result; } +int runTestBug45497(NDBT_Context* ctx, NDBT_Step* step) +{ + int result = NDBT_OK; + int loops = ctx->getNumLoops(); + Vector mgmds; + + while(true) + { + NdbMgmd* mgmd = new NdbMgmd(); + + // Set quite short timeout + if (!mgmd->set_timeout(1000)) + { + result = NDBT_FAILED; + break; + } + + if (mgmd->connect()) + { + mgmds.push_back(mgmd); + g_info << "connections: " << mgmds.size() << endl; + continue; + } + + g_err << "Failed to make another connection, connections: " + << mgmds.size() << endl; + + + // Disconnect some connections + int to_disconnect = 10; + while(mgmds.size() && to_disconnect--) + { + g_info << "disconnnect, connections: " << mgmds.size() << endl; + NdbMgmd* mgmd = mgmds[0]; + NdbMgmd* mgmd = mgmds[0]; + mgmds.erase(0); + delete mgmd; + } + + if (loops-- == 0) + break; + } + + while(mgmds.size()) + { + NdbMgmd* mgmd = mgmds[0]; + mgmds.erase(0); + delete mgmd; + } + + return result; +} + + NDBT_TESTSUITE(testMgm); TESTCASE("SingleUserMode", "Test single user mode"){ @@ -828,6 +881,12 @@ INITIALIZER(runTestMgmApiStructEventTimeout); } + +TESTCASE("Bug45497", + "Connect to ndb_mgmd until it can't handle more connections"){ + STEP(runTestBug45497); +} + NDBT_TESTSUITE_END(testMgm); int main(int argc, const char** argv){ @@ -836,3 +895,5 @@ return testMgm.execute(argc, argv); } +template class Vector; +