Bug #32461 | mysql_real_connect() hangs on connect attempt to absent server on Windows Vista | ||
---|---|---|---|
Submitted: | 16 Nov 2007 20:57 | Modified: | 9 Dec 2007 16:18 |
Reporter: | Annabel Lennox | Email Updates: | |
Status: | Can't repeat | Impact on me: | |
Category: | MySQL Server: C API (client library) | Severity: | S1 (Critical) |
Version: | 5.0.37 | OS: | Windows (Vista) |
Assigned to: | CPU Architecture: | Any |
[16 Nov 2007 20:57]
Annabel Lennox
[16 Nov 2007 22:19]
MySQL Verification Team
Thank you for the bug report. Could you please provide a code test case I wasn't able to repeat on Windows Vista Ultimate the below test code: Microsoft Windows [versão 6.0.6000] Copyright (c) 2006 Microsoft Corporation. Todos os direitos reservados. c:\dev>c:\temp\bug32461 Error: Can't connect to MySQL server on 'localhost' (10061) c:\dev> #include <my_global.h> #include <m_string.h> #include "mysql.h" #define DB_HOST "localhost" #define DB_USER "root" #define DB_PASSW "" #define DB_NAME "test" #define DB_PORT 3306 #define DB_UNIX_SOCKET NULL void main( void ) { MYSQL mysql; mysql_init(&mysql); if (!mysql_real_connect(&mysql,NULL,DB_USER,DB_PASSW,NULL,DB_PORT,NULL,0)) { printf("Error: %s\n",mysql_error(&mysql)); return; } else printf("Connected to the server: %s\n",mysql_get_server_info(&mysql)); mysql_close(&mysql); } Thanks in advance.
[26 Nov 2007 15:12]
Annabel Lennox
I was able to reproduce the problem using your test code sample from the previous comment. The call to mysql_real_connect() does not return, but instead hangs. We are using Windows Vista Business, rather than Ultimate. Is Ultimate necessary for mysql? Also, I am building with Visual Studio 2005 (SP1).
[26 Nov 2007 15:23]
MySQL Verification Team
Thank you for the feedback. I don't think the Vista version does difference, anyway I will ask to my co-worker to test on her Windows Vista too.
[26 Nov 2007 16:46]
Annabel Lennox
I also ran the test adding a call to time() before and after the call to mysql_real_connect(), printf'ing the timestamp. The call to mysql_real_connect took 30 minutes to return.
[29 Nov 2007 13:20]
Annabel Lennox
I have some more information that might help. I've been trying to code a workaround for this, and the following may help in looking at why the function doesn't return right away with a failure to connect. Here is my workaround: Instead of first calling mysql_real_connect() to test whether the db server is running and can be connected to, do this sequence: 1. Open a Windows socket. 2. Set it to nonblocking. 3. Call connect() on the socket; it will return with WSAEWOULDBLOCK. 4. Call select() on the socket for readability with a 5 second timeout. 5. If the select() returns without an error or timeout, then call mysql_real_connect(). The code is as follows. It is called each time I need to test whether the server is running, before I connect. This is done the first time checking to see if we need to start the server, and also in a timed loop after we have started the server until the server accepts connections. /***Start code sample***/ SOCKET sc; //Socket for testing SOCKADDR_IN sca; int i=1; struct timeval tv; fd_set read_fd; tv.tv_sec = 5; //Five second timeout tv.tv_usec = 0; sc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sc == INVALID_SOCKET) { printf("Error creating socket for testing db server port: %d", WSAGetLastError()); return 0; } if(ioctlsocket(sc, FIONBIO, (u_long FAR*)&i) != 0) { //set nonblocking printf("Could not set db server test socket nonblocking"); closesocket(sc); return 0; } sca.sin_family = AF_INET; sca.sin_addr.s_addr = ntohl(0x7F000001); /* 127.0.0.1 in hex */ sca.sin_port = htons((uint16)3306); printf("Calling nonblocking connect() for db server port test"); if (connect(sc, (LPSOCKADDR)&sca, sizeof(struct sockaddr)) == SOCKET_ERROR) { if(WSAGetLastError() != WSAEWOULDBLOCK) { printf("Could not connect to db server port; error"); closesocket(sc); return 0; } } //now call select() with timeout printf("Testing db server port select()"); memset(&read_fd, 0, sizeof(fd_set)); FD_SET(sc, &read_fd); i = select(sc, &read_fd, NULL, NULL, &tv); if(i <= 0) { //A timeout in this case means server is not running or responding. printf("db server port select() returned %s", i ? "error" : "timeout"); closesocket(sc); return 0; } closesocket(sc); //After this point, call mysql_real_connect() because we got a response... /***End of code sample***/ The most important part is setting the socket to nonblocking, otherwise the connect() can hang intermittently, from a few minutes to indefinitely, if the server is not available. I am wondering if this is also happening within mysql_real_connect().
[9 Dec 2007 16:18]
Sveta Smirnova
Thank you for the report. I can not repeat described behavior with version 5.0.46 also. So I close the report as "Can't repeat"
[4 Feb 2010 18:27]
Serge Lussier
Please!!! Do not close this issue: I am experiencing the same behaviour in Linux!: here is my code samples: short dbms data : namespace db { struct arDBData{ std::string name, host, user, pass, db; }; arDBData* db_data; static std::map<std::string, arDBData*> arDBDictionary; void ArknSQL::InitDBMS(){ std::cerr << __PRETTY_FUNCTION__ << std::endl; arDBData* dt; dt = new arDBData; dt->name = "arCMS"; dt->host = "localhost"; //"172.16.3.30 hangs! dt->user = "arCMS"; dt->pass = {the_password} dt->db = "arCMS"; arDBDictionary["arCMS"] = dt; dt = new arDBData; dt->name = "arInv"; dt->host = "172.15.3.30"; // not used yet dt->user = "arInv"; dt->pass = {the password} dt->db = "arInv"; arDBDictionary["arInv"] = dt; } // ------------- continue ------------ config code: [...] db_data = arDBDictionary[_dbmsName]; _connected = false; if(! mysql_init(&_my) ){ (*this) << new SQLError(&_my, "db::Init"); return 0; } [..] connection code: [...] std::cerr << __PRETTY_FUNCTION__ << "Connecting with params:" << std::endl; std::cerr << "host:" << db_data->host << " user: " << db_data->user << std::endl; if ( !mysql_real_connect ( &_my, db_data->host.c_str(), db_data->user.c_str(), db_data->pass.c_str(), db_data->db.c_str(),0,0l,0 ) ) { std::cerr << "failed connexion..." << std::endl; ( *this ) << new SQLError ( &_my, "Connecting to MySQL" ); QueryError_( LastError() ); return 0; } std::cerr << "successfull connexion" << std::endl; _connected = true; return 1; If I use ip address instead of "localhost" it hangs ( nothing to do with OS though ). And I tried to connect from cndline and the connection is working - so it has todo with libmysqlclient it self ?? ------------------------------------------------------------------ server mysqld Ver 5.1.37-1ubuntu5 for debian-linux-gnu on i486 ((Ubuntu)) my.cnf::BindAddress = "172.16.3.30" -- ok Thank you and sorry for my poor english and code...
[4 Feb 2010 20:39]
Sveta Smirnova
Serge Lussier, thank you for the feedback. Could you please try with current version 5.1.43 available from http://dev.mysql.com/downloads?
[1 Nov 2010 14:28]
liu hickey
The workaround way is to set timeout for mysql before mysql_real_connection(), which is tested based on mysql-5.1.47 on Linux: unsigned int time_out=1; mysql_options(mysql_db,MYSQL_OPT_CONNECT_TIMEOUT,(char*)&time_out); With IP unaccessible/accessible loops, the mysql_real_connection never block on _recv for very long time anymore, while connection would be returned from server side with-in 1sec if server is down. From some sense, it's still an open bug of engine side. It still could be repeated very high frequency tested by dbt2-0.4 as client for mysql-5.1.47.
[8 Mar 2011 15:55]
michael ole olsen
FYI the bug is still there in Debian Lenny: ii libmysqlclient15-dev 5.0.51a-24+lenny5 MySQL database development files I'm fetching unstable branch now, tried all options both for READ and CONNECT timeout and also tried setting mysql.options directly.
[10 Oct 2011 11:23]
Amiyakanta Sahu
I tried this on Fedora Linux and getting the same problem. But by setting timeout option using mysql_options(&mysql,MYSQL_OPT_CONNECT_TIMEOUT,(char*)&time_out) after mysql_init(&mysql) and before mysql_real_connect(&mysql,NULL,DB_USER,DB_PASSW,NULL,DB_PORT,NULL,0) I am bale get a timeout error.