| 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.
