You've already forked mariadb-connector-c
mirror of
https://github.com/mariadb-corporation/mariadb-connector-c.git
synced 2025-08-07 02:42:49 +03:00
Fix for asynchronous (reconnect)
Fixed memory leak after reconnect/change user
This commit is contained in:
@@ -165,7 +165,16 @@ INCLUDE(${CMAKE_SOURCE_DIR}/cmake/CheckFunctions.cmake)
|
||||
# check for various types
|
||||
INCLUDE(${CMAKE_SOURCE_DIR}/cmake/CheckTypes.cmake)
|
||||
|
||||
IF(WITH_SSL STREQUAL "OPENSSL")
|
||||
IF(NOT WITH_SSL)
|
||||
IF(WIN32)
|
||||
SET(WITH_SSL "SCHANNEL")
|
||||
ELSE()
|
||||
SET(WITH_SSL "OPENSSL")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
IF(NOT WITH_SSL STREQUAL "OFF")
|
||||
IF(WITH_SSL STREQUAL "OPENSSL")
|
||||
FIND_PACKAGE(OpenSSL)
|
||||
IF(OPENSSL_FOUND)
|
||||
ADD_DEFINITIONS(-DHAVE_OPENSSL -DHAVE_SSL)
|
||||
@@ -174,8 +183,8 @@ IF(WITH_SSL STREQUAL "OPENSSL")
|
||||
ELSE()
|
||||
MESSAGE(FATAL "OpenSSL not found")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
IF(WITH_SSL STREQUAL "GNUTLS")
|
||||
ENDIF()
|
||||
IF(WITH_SSL STREQUAL "GNUTLS")
|
||||
FIND_PACKAGE(GnuTLS)
|
||||
IF(GNUTLS_FOUND)
|
||||
ADD_DEFINITIONS(-DHAVE_GNUTLS -DHAVE_SSL)
|
||||
@@ -184,21 +193,17 @@ IF(WITH_SSL STREQUAL "GNUTLS")
|
||||
ELSE()
|
||||
MESSAGE(FATAL "GnuTLS not found")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
IF(WIN32)
|
||||
ENDIF()
|
||||
IF(WIN32)
|
||||
IF(WITH_SSL STREQUAL "SCHANNEL")
|
||||
MESSAGE(STATUS "SSL_TYPE ${SSL_TYPE}")
|
||||
ADD_DEFINITIONS(-DHAVE_SCHANNEL -DHAVE_SSL)
|
||||
SET(SSL_SOURCES "${CMAKE_SOURCE_DIR}/libmariadb/secure/schannel.c" "${CMAKE_SOURCE_DIR}/libmariadb/secure/ma_schannel.c")
|
||||
INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/plugins/pvio/")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
MARK_AS_ADVANCED(SSL_SOURCES)
|
||||
|
||||
|
||||
IF(WITH_SQLITE)
|
||||
ADD_DEFINITIONS(-DHAVE_SQLITE)
|
||||
MARK_AS_ADVANCED(SSL_SOURCES)
|
||||
ENDIF()
|
||||
|
||||
IF(NOT WIN32)
|
||||
|
@@ -76,6 +76,7 @@ extern const char *mariadb_client_errors[]; /* Error messages */
|
||||
#define CR_NO_STMT_METADATA 2052
|
||||
#define CR_NOT_IMPLEMENTED 2054
|
||||
#define CR_SERVER_LOST_EXTENDED 2055
|
||||
#define CR_STMT_CLOSED 2056
|
||||
#define CR_NEW_STMT_METADATA 2057
|
||||
#define CR_AUTH_PLUGIN_CANNOT_LOAD 2058
|
||||
#define CR_ALREADY_CONNECTED 2059
|
||||
|
@@ -16,9 +16,17 @@
|
||||
struct st_ma_pvio_methods;
|
||||
typedef struct st_ma_pvio_methods PVIO_METHODS;
|
||||
|
||||
#define IS_ASYNC_ACTIVE(a) \
|
||||
((a)->mysql->options.extension && (a)->mysql->options.extension->async_context && \
|
||||
(a)->mysql->options.extension->async_context->active)
|
||||
#define IS_PVIO_ASYNC(a) \
|
||||
((a)->mysql && (a)->mysql->options.extension && (a)->mysql->options.extension->async_context)
|
||||
|
||||
#define IS_PVIO_ASYNC_ACTIVE(a) \
|
||||
(IS_PVIO_ASYNC(a)&& (a)->mysql->options.extension->async_context->active)
|
||||
|
||||
#define IS_MYSQL_ASYNC(a) \
|
||||
((a)->options.extension && (a)->options.extension->async_context)
|
||||
|
||||
#define IS_MYSQL_ASYNC_ACTIVE(a) \
|
||||
(IS_MYSQL_ASYNC(a)&& (a)->options.extension->async_context->active)
|
||||
|
||||
#ifndef ssl_defined
|
||||
#define ssl_defined
|
||||
@@ -101,6 +109,7 @@ struct st_ma_pvio_methods
|
||||
my_bool (*get_handle)(MARIADB_PVIO *pvio, void *handle);
|
||||
my_bool (*is_blocking)(MARIADB_PVIO *pvio);
|
||||
my_bool (*is_alive)(MARIADB_PVIO *pvio);
|
||||
my_bool (*has_data)(MARIADB_PVIO *pvio, ssize_t *data_len);
|
||||
};
|
||||
|
||||
/* Function prototypes */
|
||||
@@ -121,5 +130,6 @@ int ma_pvio_wait_io_or_timeout(MARIADB_PVIO *pvio, my_bool is_read, int timeout)
|
||||
my_bool ma_pvio_connect(MARIADB_PVIO *pvio, MA_PVIO_CINFO *cinfo);
|
||||
my_bool ma_pvio_is_alive(MARIADB_PVIO *pvio);
|
||||
my_bool ma_pvio_get_handle(MARIADB_PVIO *pvio, void *handle);
|
||||
my_bool ma_pvio_has_data(MARIADB_PVIO *pvio, ssize_t *length);
|
||||
|
||||
#endif /* _ma_pvio_h_ */
|
||||
|
@@ -136,7 +136,7 @@ const char *client_errors[]=
|
||||
/* 2053 */ "",
|
||||
/* 2054 */ "This feature is not implemented or disabled",
|
||||
/* 2055 */ "Lost connection to MySQL server at '%s', system error: %d",
|
||||
/* 2056 */ "",
|
||||
/* 2056 */ "Server closed statement due to a prior %s function call",
|
||||
/* 2057 */ "The number of parameters in bound buffers differs from number of columns in resultset",
|
||||
/* 2058 */ "Plugin %s could not be loaded: %s",
|
||||
/* 2059 */ "Can't connect twice. Already connected",
|
||||
|
@@ -384,6 +384,13 @@ mthd_my_send_cmd(MYSQL *mysql,enum enum_server_command command, const char *arg,
|
||||
if (!arg)
|
||||
arg="";
|
||||
|
||||
/* check if connection kills itself */
|
||||
if (command == COM_PROCESS_KILL)
|
||||
{
|
||||
unsigned long thread_id= uint4korr(arg);
|
||||
if (thread_id == mysql->thread_id)
|
||||
skipp_check= 1;
|
||||
}
|
||||
if (net_write_command(net,(uchar) command,arg,
|
||||
length ? length : (ulong) strlen(arg)))
|
||||
{
|
||||
@@ -1684,10 +1691,36 @@ error:
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
struct my_hook_data {
|
||||
MYSQL *orig_mysql;
|
||||
MYSQL *new_mysql;
|
||||
/* This is always NULL currently, but restoring does not hurt just in case. */
|
||||
MARIADB_PVIO *orig_pvio;
|
||||
};
|
||||
/*
|
||||
Callback hook to make the new VIO accessible via the old MYSQL to calling
|
||||
application when suspending a non-blocking call during automatic reconnect.
|
||||
*/
|
||||
static void
|
||||
my_suspend_hook(my_bool suspend, void *data)
|
||||
{
|
||||
struct my_hook_data *hook_data= (struct my_hook_data *)data;
|
||||
if (suspend)
|
||||
{
|
||||
hook_data->orig_pvio= hook_data->orig_mysql->net.pvio;
|
||||
hook_data->orig_mysql->net.pvio= hook_data->new_mysql->net.pvio;
|
||||
}
|
||||
else
|
||||
hook_data->orig_mysql->net.pvio= hook_data->orig_pvio;
|
||||
}
|
||||
|
||||
|
||||
static my_bool mysql_reconnect(MYSQL *mysql)
|
||||
{
|
||||
MYSQL tmp_mysql;
|
||||
LIST *li_stmt= mysql->stmts;
|
||||
struct my_hook_data hook_data;
|
||||
struct mysql_async_context *ctxt= NULL;
|
||||
|
||||
DBUG_ENTER("mysql_reconnect");
|
||||
|
||||
if (!mysql->reconnect ||
|
||||
@@ -1705,19 +1738,21 @@ static my_bool mysql_reconnect(MYSQL *mysql)
|
||||
/* don't reread options from configuration files */
|
||||
tmp_mysql.options.my_cnf_group= tmp_mysql.options.my_cnf_file= NULL;
|
||||
|
||||
/* make sure that we reconnect with the same character set */
|
||||
if (!tmp_mysql.options.charset_name ||
|
||||
strcmp(tmp_mysql.options.charset_name, mysql->charset->csname))
|
||||
if (IS_MYSQL_ASYNC_ACTIVE(mysql))
|
||||
{
|
||||
my_free(tmp_mysql.options.charset_name);
|
||||
tmp_mysql.options.charset_name= my_strdup(mysql->charset->csname, MYF(MY_WME));
|
||||
hook_data.orig_mysql= mysql;
|
||||
hook_data.new_mysql= &tmp_mysql;
|
||||
hook_data.orig_pvio= mysql->net.pvio;
|
||||
my_context_install_suspend_resume_hook(ctxt, my_suspend_hook, &hook_data);
|
||||
}
|
||||
|
||||
tmp_mysql.reconnect= mysql->reconnect;
|
||||
if (!mysql_real_connect(&tmp_mysql,mysql->host,mysql->user,mysql->passwd,
|
||||
mysql->db, mysql->port, mysql->unix_socket,
|
||||
mysql->client_flag | CLIENT_REMEMBER_OPTIONS))
|
||||
mysql->client_flag | CLIENT_REMEMBER_OPTIONS) ||
|
||||
mysql_set_character_set(&tmp_mysql, mysql->charset->csname))
|
||||
{
|
||||
if (ctxt)
|
||||
my_context_install_suspend_resume_hook(ctxt, NULL, NULL);
|
||||
/* don't free options (CONC-118) */
|
||||
memset(&tmp_mysql.options, 0, sizeof(struct st_mysql_options));
|
||||
my_set_error(mysql, tmp_mysql.net.last_errno,
|
||||
@@ -1727,19 +1762,7 @@ static my_bool mysql_reconnect(MYSQL *mysql)
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
/* reset the connection in all active statements
|
||||
todo: check stmt->mysql in mysql_stmt* functions ! */
|
||||
for (;li_stmt;li_stmt= li_stmt->next)
|
||||
{
|
||||
MYSQL_STMT *stmt= (MYSQL_STMT *)li_stmt->data;
|
||||
|
||||
if (stmt->state != MYSQL_STMT_INITTED)
|
||||
{
|
||||
stmt->state= MYSQL_STMT_INITTED;
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0);
|
||||
}
|
||||
}
|
||||
|
||||
tmp_mysql.reconnect= mysql->reconnect;
|
||||
tmp_mysql.free_me= mysql->free_me;
|
||||
tmp_mysql.stmts= mysql->stmts;
|
||||
mysql->stmts= NULL;
|
||||
@@ -1747,16 +1770,31 @@ static my_bool mysql_reconnect(MYSQL *mysql)
|
||||
/* Don't free options, we moved them to tmp_mysql */
|
||||
memset(&mysql->options, 0, sizeof(mysql->options));
|
||||
mysql->free_me=0;
|
||||
mysql->stmts= NULL;
|
||||
mysql_close(mysql);
|
||||
*mysql=tmp_mysql;
|
||||
mysql->reconnect= 1;
|
||||
mysql->net.pvio->mysql= mysql;
|
||||
net_clear(&mysql->net);
|
||||
mysql->affected_rows= ~(my_ulonglong) 0;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
static void ma_invalidate_stmts(MYSQL *mysql, const char *function_name)
|
||||
{
|
||||
if (mysql->stmts)
|
||||
{
|
||||
LIST *li_stmt= mysql->stmts;
|
||||
|
||||
for (; li_stmt; li_stmt= li_stmt->next)
|
||||
{
|
||||
MYSQL_STMT *stmt= (MYSQL_STMT *)li_stmt->data;
|
||||
stmt->mysql= NULL;
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_STMT_CLOSED, SQLSTATE_UNKNOWN, function_name);
|
||||
}
|
||||
mysql->stmts= NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
** Change user and database
|
||||
**************************************************************************/
|
||||
@@ -1786,36 +1824,33 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
|
||||
else
|
||||
mysql->charset=default_charset_info;
|
||||
|
||||
mysql->user= (char *)user;
|
||||
mysql->passwd= (char *)passwd;
|
||||
mysql->db= (char *)db;
|
||||
mysql->user= my_strdup(user ? user : "", MYF(MY_WME));
|
||||
mysql->passwd= my_strdup(passwd ? passwd : "", MYF(MY_WME));
|
||||
|
||||
/* db will be set in run_plugin_auth */
|
||||
mysql->db= 0;
|
||||
rc= run_plugin_auth(mysql, 0, 0, 0, db);
|
||||
|
||||
/* COM_CHANGE_USER always releases prepared statements, so we need to invalidate them */
|
||||
ma_invalidate_stmts(mysql, "mysql_change_user()");
|
||||
|
||||
if (rc==0)
|
||||
{
|
||||
LIST *li_stmt= mysql->stmts;
|
||||
my_free(s_user);
|
||||
my_free(s_passwd);
|
||||
my_free(s_db);
|
||||
|
||||
if (!(mysql->user= my_strdup(user,MYF(MY_WME))) ||
|
||||
!(mysql->passwd=my_strdup(passwd,MYF(MY_WME))) ||
|
||||
!(mysql->db= db ? my_strdup(db,MYF(MY_WME)) : 0))
|
||||
if (db && !(mysql->db= my_strdup(db,MYF(MY_WME))))
|
||||
{
|
||||
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate, 0);
|
||||
rc= 1;
|
||||
}
|
||||
|
||||
for (;li_stmt;li_stmt= li_stmt->next)
|
||||
{
|
||||
MYSQL_STMT *stmt= (MYSQL_STMT *)li_stmt->data;
|
||||
stmt->mysql= NULL;
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0);
|
||||
}/* detach stmts */
|
||||
mysql->stmts= NULL;
|
||||
|
||||
} else
|
||||
{
|
||||
my_free(mysql->user);
|
||||
my_free(mysql->passwd);
|
||||
my_free(mysql->db);
|
||||
|
||||
mysql->user= s_user;
|
||||
mysql->passwd= s_passwd;
|
||||
mysql->db= s_db;
|
||||
@@ -1870,6 +1905,7 @@ static void mysql_close_options(MYSQL *mysql)
|
||||
my_free(mysql->options.my_cnf_group);
|
||||
my_free(mysql->options.charset_dir);
|
||||
my_free(mysql->options.charset_name);
|
||||
my_free(mysql->options.bind_address);
|
||||
my_free(mysql->options.ssl_key);
|
||||
my_free(mysql->options.ssl_cert);
|
||||
my_free(mysql->options.ssl_ca);
|
||||
@@ -1946,12 +1982,9 @@ void mysql_close_slow_part(MYSQL *mysql)
|
||||
void STDCALL
|
||||
mysql_close(MYSQL *mysql)
|
||||
{
|
||||
MYSQL_STMT *stmt;
|
||||
DBUG_ENTER("mysql_close");
|
||||
if (mysql) /* Some simple safety */
|
||||
{
|
||||
LIST *li_stmt= mysql->stmts;
|
||||
|
||||
if (mysql->net.conn_hdlr && mysql->net.conn_hdlr->data)
|
||||
{
|
||||
void *p= (void *)mysql->net.conn_hdlr;
|
||||
@@ -1963,14 +1996,8 @@ mysql_close(MYSQL *mysql)
|
||||
if (mysql->methods)
|
||||
mysql->methods->db_close(mysql);
|
||||
|
||||
/* reset the connection in all active statements
|
||||
todo: check stmt->mysql in mysql_stmt* functions ! */
|
||||
for (;li_stmt;li_stmt= li_stmt->next)
|
||||
{
|
||||
stmt= (MYSQL_STMT *)li_stmt->data;
|
||||
stmt->mysql= NULL;
|
||||
SET_CLIENT_STMT_ERROR(stmt, CR_SERVER_LOST, SQLSTATE_UNKNOWN, 0);
|
||||
}
|
||||
/* reset the connection in all active statements */
|
||||
ma_invalidate_stmts(mysql, "mysql_close()");
|
||||
mysql_close_memory(mysql);
|
||||
mysql_close_options(mysql);
|
||||
mysql->host_info=mysql->user=mysql->passwd=mysql->db=0;
|
||||
|
@@ -185,7 +185,7 @@ static size_t ma_pvio_read_async(MARIADB_PVIO *pvio, uchar *buffer, size_t lengt
|
||||
/* todo: async */
|
||||
if (pvio->methods->async_read)
|
||||
res= pvio->methods->async_read(pvio, buffer, length);
|
||||
if (res >= 0 /* || IS_BLOCKING_ERROR()*/)
|
||||
if (res >= 0 || IS_BLOCKING_ERROR())
|
||||
return res;
|
||||
b->events_to_wait_for= MYSQL_WAIT_READ;
|
||||
if (timeout >= 0)
|
||||
@@ -211,14 +211,14 @@ size_t ma_pvio_read(MARIADB_PVIO *pvio, uchar *buffer, size_t length)
|
||||
if (!pvio)
|
||||
return -1;
|
||||
|
||||
if (pvio && pvio->async_context && pvio->async_context->active)
|
||||
if (IS_PVIO_ASYNC_ACTIVE(pvio))
|
||||
{
|
||||
r= ma_pvio_read_async(pvio, buffer, length);
|
||||
goto end;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pvio->async_context)
|
||||
if (IS_PVIO_ASYNC(pvio))
|
||||
{
|
||||
/*
|
||||
If switching from non-blocking to blocking API usage, set the socket
|
||||
@@ -232,8 +232,10 @@ size_t ma_pvio_read(MARIADB_PVIO *pvio, uchar *buffer, size_t length)
|
||||
/* secure connection */
|
||||
#ifdef HAVE_SSL
|
||||
if (pvio->cssl)
|
||||
{
|
||||
r= ma_pvio_ssl_read(pvio->cssl, buffer, length);
|
||||
else
|
||||
goto end;
|
||||
}
|
||||
#endif
|
||||
if (pvio->methods->read)
|
||||
r= pvio->methods->read(pvio, buffer, length);
|
||||
@@ -330,32 +332,24 @@ size_t ma_pvio_write(MARIADB_PVIO *pvio, const uchar *buffer, size_t length)
|
||||
if (!pvio)
|
||||
return -1;
|
||||
|
||||
if (pvio_callback)
|
||||
{
|
||||
void (*callback)(int mode, MYSQL *mysql, const uchar *buffer, size_t length);
|
||||
LIST *p= pvio_callback;
|
||||
while (p)
|
||||
{
|
||||
callback= p->data;
|
||||
callback(1, pvio->mysql, buffer, length);
|
||||
p= p->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* secure connection */
|
||||
#ifdef HAVE_SSL
|
||||
if (pvio->cssl)
|
||||
{
|
||||
r= ma_pvio_ssl_write(pvio->cssl, buffer, length);
|
||||
goto end;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (IS_ASYNC_ACTIVE(pvio))
|
||||
// printf("No ssl (write): %x\n", pvio->cssl);
|
||||
if (IS_PVIO_ASYNC_ACTIVE(pvio))
|
||||
{
|
||||
r= ma_pvio_write_async(pvio, buffer, length);
|
||||
goto end;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pvio->async_context)
|
||||
if (IS_PVIO_ASYNC(pvio))
|
||||
{
|
||||
/*
|
||||
If switching from non-blocking to blocking API usage, set the socket
|
||||
@@ -408,11 +402,43 @@ my_bool ma_pvio_get_handle(MARIADB_PVIO *pvio, void *handle)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ ma_pvio_wait_async */
|
||||
static my_bool
|
||||
ma_pvio_wait_async(struct mysql_async_context *b, enum enum_pvio_io_event event,
|
||||
int timeout)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case VIO_IO_EVENT_READ:
|
||||
b->events_to_wait_for = MYSQL_WAIT_READ;
|
||||
break;
|
||||
case VIO_IO_EVENT_WRITE:
|
||||
b->events_to_wait_for = MYSQL_WAIT_WRITE;
|
||||
break;
|
||||
case VIO_IO_EVENT_CONNECT:
|
||||
b->events_to_wait_for = MYSQL_WAIT_WRITE | IF_WIN(0, MYSQL_WAIT_EXCEPT);
|
||||
break;
|
||||
}
|
||||
|
||||
if (timeout >= 0)
|
||||
{
|
||||
b->events_to_wait_for |= MYSQL_WAIT_TIMEOUT;
|
||||
b->timeout_value= timeout;
|
||||
}
|
||||
if (b->suspend_resume_hook)
|
||||
(*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data);
|
||||
my_context_yield(&b->async_context);
|
||||
if (b->suspend_resume_hook)
|
||||
(*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data);
|
||||
return (b->events_occured & MYSQL_WAIT_TIMEOUT) ? 0 : 1;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ ma_pvio_wait_io_or_timeout */
|
||||
int ma_pvio_wait_io_or_timeout(MARIADB_PVIO *pvio, my_bool is_read, int timeout)
|
||||
{
|
||||
if (pvio && pvio->async_context && pvio->async_context->active)
|
||||
return my_io_wait_async(pvio->async_context,
|
||||
if (IS_PVIO_ASYNC_ACTIVE(pvio))
|
||||
return ma_pvio_wait_async(pvio->mysql->options.extension->async_context,
|
||||
(is_read) ? VIO_IO_EVENT_READ : VIO_IO_EVENT_WRITE,
|
||||
timeout);
|
||||
|
||||
@@ -450,6 +476,19 @@ my_bool ma_pvio_is_blocking(MARIADB_PVIO *pvio)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ ma_pvio_has_data */
|
||||
my_bool ma_pvio_has_data(MARIADB_PVIO *pvio, ssize_t *data_len)
|
||||
{
|
||||
/* check if we still have unread data in cache */
|
||||
if (pvio->cache)
|
||||
if (pvio->cache_pos > pvio->cache)
|
||||
return pvio->cache_pos - pvio->cache;
|
||||
if (pvio && pvio->methods->has_data)
|
||||
return pvio->methods->has_data(pvio, data_len);
|
||||
return 1;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
/* {{{ my_bool ma_pvio_start_ssl */
|
||||
my_bool ma_pvio_start_ssl(MARIADB_PVIO *pvio)
|
||||
@@ -463,7 +502,7 @@ my_bool ma_pvio_start_ssl(MARIADB_PVIO *pvio)
|
||||
}
|
||||
if (ma_pvio_ssl_connect(pvio->cssl))
|
||||
{
|
||||
my_free((gptr)pvio->cssl);
|
||||
my_free(pvio->cssl);
|
||||
pvio->cssl= NULL;
|
||||
return 1;
|
||||
}
|
||||
|
@@ -415,7 +415,8 @@ unsigned char *mysql_net_store_length(unsigned char *packet, size_t length)
|
||||
int store_param(MYSQL_STMT *stmt, int column, unsigned char **p)
|
||||
{
|
||||
DBUG_ENTER("store_param");
|
||||
DBUG_PRINT("info", ("column: %d type: x%x", column, stmt->params[column].buffer_type));
|
||||
DBUG_PRINT("info", ("column: %d type: %d", column, stmt->params[column].buffer_type));
|
||||
printf("type: %d\n", column, stmt->params[column].buffer_type);
|
||||
switch (stmt->params[column].buffer_type) {
|
||||
case MYSQL_TYPE_TINY:
|
||||
int1store(*p, *(uchar *)stmt->params[column].buffer);
|
||||
|
@@ -134,37 +134,6 @@ my_connect_async(MARIADB_PVIO *pvio,
|
||||
#endif
|
||||
#endif
|
||||
|
||||
my_bool
|
||||
my_io_wait_async(struct mysql_async_context *b, enum enum_pvio_io_event event,
|
||||
int timeout)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case VIO_IO_EVENT_READ:
|
||||
b->events_to_wait_for = MYSQL_WAIT_READ;
|
||||
break;
|
||||
case VIO_IO_EVENT_WRITE:
|
||||
b->events_to_wait_for = MYSQL_WAIT_WRITE;
|
||||
break;
|
||||
case VIO_IO_EVENT_CONNECT:
|
||||
b->events_to_wait_for = MYSQL_WAIT_WRITE | IF_WIN(0, MYSQL_WAIT_EXCEPT);
|
||||
break;
|
||||
}
|
||||
|
||||
if (timeout >= 0)
|
||||
{
|
||||
b->events_to_wait_for |= MYSQL_WAIT_TIMEOUT;
|
||||
b->timeout_value= timeout;
|
||||
}
|
||||
if (b->suspend_resume_hook)
|
||||
(*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data);
|
||||
my_context_yield(&b->async_context);
|
||||
if (b->suspend_resume_hook)
|
||||
(*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data);
|
||||
return (b->events_occured & MYSQL_WAIT_TIMEOUT) ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_SSL_FIXME
|
||||
static my_bool
|
||||
my_ssl_async_check_result(int res, struct mysql_async_context *b, MARIADB_SSL *cssl)
|
||||
|
@@ -179,67 +179,11 @@ static my_bool net_realloc(NET *net, size_t length)
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
/* check if the socket is still alive */
|
||||
static my_bool net_check_socket_status(my_socket sock)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
struct pollfd poll_fd;
|
||||
#else
|
||||
FD_SET sfds;
|
||||
struct timeval tv= {0,0};
|
||||
#endif
|
||||
int res;
|
||||
#ifndef _WIN32
|
||||
memset(&poll_fd, 0, sizeof(struct pollfd));
|
||||
poll_fd.events= POLLPRI | POLLIN;
|
||||
poll_fd.fd= sock;
|
||||
|
||||
res= poll(&poll_fd, 1, 0);
|
||||
if (res <= 0) /* timeout or error */
|
||||
return FALSE;
|
||||
if (!(poll_fd.revents & (POLLIN | POLLPRI)))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
#else
|
||||
/* We can't use the WSAPoll function, it's broken :-(
|
||||
(see Windows 8 Bugs 309411 - WSAPoll does not report failed connections)
|
||||
Instead we need to use select function:
|
||||
If TIMEVAL is initialized to {0, 0}, select will return immediately;
|
||||
this is used to poll the state of the selected sockets.
|
||||
*/
|
||||
FD_ZERO(&sfds);
|
||||
FD_SET(sock, &sfds);
|
||||
|
||||
res= select((int)sock + 1, &sfds, NULL, NULL, &tv);
|
||||
if (res > 0 && FD_ISSET(sock, &sfds))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/* Remove unwanted characters from connection */
|
||||
/* Remove unwanted characters from connection */
|
||||
|
||||
void net_clear(NET *net)
|
||||
{
|
||||
my_socket sock;
|
||||
DBUG_ENTER("net_clear");
|
||||
|
||||
ma_pvio_get_handle(net->pvio, &sock);
|
||||
|
||||
/* see conc-71: we need to check the socket status first:
|
||||
if the socket is dead we set net->error, so net_flush
|
||||
will report an error */
|
||||
while (net_check_socket_status(sock))
|
||||
{
|
||||
if ((ssize_t)ma_pvio_cache_read(net->pvio, (gptr)net->buff, (size_t) net->max_packet) <= 0)
|
||||
{
|
||||
net->error= 2;
|
||||
DBUG_PRINT("info", ("socket disconnected"));
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
}
|
||||
net->compress_pkt_nr= net->pkt_nr=0; /* Ready for new command */
|
||||
net->write_pos=net->buff;
|
||||
DBUG_VOID_RETURN;
|
||||
|
@@ -235,6 +235,12 @@ ssize_t ma_ssl_pull(gnutls_transport_ptr_t ptr, void* data, size_t len)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int ma_ssl_pull_timeout(gnutls_transport_ptr_t ptr, unsigned int ms)
|
||||
{
|
||||
MARIADB_PVIO *pvio= (MARIADB_PVIO *)ptr;
|
||||
return pvio->methods->wait_io_or_timeout(pvio, 0, ms);
|
||||
}
|
||||
|
||||
my_bool ma_ssl_connect(MARIADB_SSL *cssl)
|
||||
{
|
||||
gnutls_session_t ssl = (gnutls_session_t)cssl->ssl;
|
||||
@@ -257,7 +263,8 @@ my_bool ma_ssl_connect(MARIADB_SSL *cssl)
|
||||
gnutls_transport_set_ptr(ssl, pvio);
|
||||
gnutls_transport_set_push_function(ssl, ma_ssl_push);
|
||||
gnutls_transport_set_pull_function(ssl, ma_ssl_pull);
|
||||
gnutls_handshake_set_timeout(ssl, mysql->options.connect_timeout);
|
||||
gnutls_transport_set_pull_timeout_function(ssl, ma_ssl_pull_timeout);
|
||||
gnutls_handshake_set_timeout(ssl, pvio->timeout[PVIO_CONNECT_TIMEOUT]);
|
||||
|
||||
do {
|
||||
ret = gnutls_handshake(ssl);
|
||||
@@ -417,3 +424,4 @@ unsigned int ma_ssl_get_finger_print(MARIADB_SSL *cssl, unsigned char *fp, unsig
|
||||
}
|
||||
|
||||
#endif /* HAVE_GNUTLS */
|
||||
|
||||
|
@@ -76,6 +76,7 @@ int pvio_socket_keepalive(MARIADB_PVIO *pvio);
|
||||
my_bool pvio_socket_get_handle(MARIADB_PVIO *pvio, void *handle);
|
||||
my_bool pvio_socket_is_blocking(MARIADB_PVIO *pvio);
|
||||
my_bool pvio_socket_is_alive(MARIADB_PVIO *pvio);
|
||||
my_bool pvio_socket_has_data(MARIADB_PVIO *pvio, ssize_t *data_len);
|
||||
|
||||
static int pvio_socket_init(char *unused1,
|
||||
size_t unused2,
|
||||
@@ -98,7 +99,8 @@ struct st_ma_pvio_methods pvio_socket_methods= {
|
||||
pvio_socket_keepalive,
|
||||
pvio_socket_get_handle,
|
||||
pvio_socket_is_blocking,
|
||||
pvio_socket_is_alive
|
||||
pvio_socket_is_alive,
|
||||
pvio_socket_has_data
|
||||
};
|
||||
|
||||
#ifndef HAVE_SOCKET_DYNAMIC
|
||||
@@ -913,11 +915,14 @@ my_bool pvio_socket_is_alive(MARIADB_PVIO *pvio)
|
||||
#ifndef _WIN32
|
||||
memset(&poll_fd, 0, sizeof(struct pollfd));
|
||||
poll_fd.events= POLLPRI | POLLIN;
|
||||
poll_fd.revents= POLLERR;
|
||||
poll_fd.fd= csock->socket;
|
||||
|
||||
res= poll(&poll_fd, 1, 0);
|
||||
if (res <= 0) /* timeout or error */
|
||||
return FALSE;
|
||||
if (!(poll_fd.revents & POLLERR))
|
||||
return FALSE;
|
||||
if (!(poll_fd.revents & (POLLIN | POLLPRI)))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
@@ -931,10 +936,35 @@ my_bool pvio_socket_is_alive(MARIADB_PVIO *pvio)
|
||||
FD_ZERO(&sfds);
|
||||
FD_SET(csock->socket, &sfds);
|
||||
|
||||
res= select((int)+csock->socket + 1, &sfds, NULL, NULL, &tv);
|
||||
res= select((int)csock->socket + 1, &sfds, NULL, NULL, &tv);
|
||||
if (res > 0 && FD_ISSET(csock->socket, &sfds))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ my_boool pvio_socket_has_data */
|
||||
my_bool pvio_socket_has_data(MARIADB_PVIO *pvio, ssize_t *data_len)
|
||||
{
|
||||
struct st_pvio_socket *csock= NULL;
|
||||
char tmp_buf[1024];
|
||||
ssize_t len;
|
||||
my_bool mode;
|
||||
|
||||
if (!pvio || !pvio->data)
|
||||
return 0;
|
||||
|
||||
csock= (struct st_pvio_socket *)pvio->data;
|
||||
/* MSG_PEEK: Peeks at the incoming data. The data is copied into the buffer,
|
||||
but is not removed from the input queue.
|
||||
*/
|
||||
pvio_socket_blocking(pvio, 0, &mode);
|
||||
len= recv(csock->socket, &tmp_buf, sizeof(tmp_buf), MSG_PEEK);
|
||||
pvio_socket_blocking(pvio, mode, 0);
|
||||
if (len < 0)
|
||||
return 1;
|
||||
*data_len= len;
|
||||
return 0;
|
||||
}
|
||||
/* }}} */
|
||||
|
@@ -39,8 +39,7 @@ static int test_conc75(MYSQL *my)
|
||||
mysql= mysql_init(NULL);
|
||||
|
||||
|
||||
mysql_options(mysql, MYSQL_OPT_RECONNECT,(const char *)"true");
|
||||
|
||||
mysql->reconnect= 1;
|
||||
mysql_real_connect(mysql, hostname, username, password, schema, port, socketname, 0| CLIENT_MULTI_RESULTS | CLIENT_REMEMBER_OPTIONS);
|
||||
|
||||
rc= mysql_query(mysql, "DROP TABLE IF EXISTS a");
|
||||
|
@@ -487,6 +487,7 @@ static int bug30472_retrieve_charset_info(MYSQL *con,
|
||||
row= mysql_fetch_row(rs);
|
||||
FAIL_IF(!row, "Couldn't fetch row");
|
||||
strcpy(character_set_client, row[1]);
|
||||
diag("cs: %s", row[1]);
|
||||
mysql_free_result(rs);
|
||||
|
||||
rc= mysql_query(con, "SHOW VARIABLES LIKE 'character_set_results'");
|
||||
|
@@ -964,7 +964,6 @@ static int test_conc117(MYSQL *mysql)
|
||||
mysql_kill(my, mysql_thread_id(my));
|
||||
sleep(5);
|
||||
|
||||
strcpy(my->host, "A");
|
||||
my->reconnect= 1;
|
||||
|
||||
mysql_query(my, "SET @a:=1");
|
||||
|
@@ -374,7 +374,7 @@ MYSQL *test_connect(struct my_tests_st *test) {
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
mysql_options(mysql, MYSQL_REPORT_DATA_TRUNCATION, "1");
|
||||
mysql_options(mysql, MYSQL_REPORT_DATA_TRUNCATION, &i);
|
||||
mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (const char *)&i);
|
||||
|
||||
/* option handling */
|
||||
|
@@ -523,10 +523,12 @@ static int test_bug12744(MYSQL *mysql)
|
||||
check_stmt_rc(rc, stmt);
|
||||
|
||||
/* set reconnect, kill and ping to reconnect */
|
||||
rc= mysql_query(mysql, "SET @a:=1");
|
||||
check_mysql_rc(rc, mysql);
|
||||
rc= mysql_options(mysql, MYSQL_OPT_RECONNECT, "1");
|
||||
check_mysql_rc(rc, mysql);
|
||||
rc= mysql_kill(mysql, mysql_thread_id(mysql));
|
||||
//check_mysql_rc(rc, mysql);
|
||||
check_mysql_rc(rc, mysql);
|
||||
|
||||
sleep(2);
|
||||
rc= mysql_ping(mysql);
|
||||
@@ -542,10 +544,10 @@ static int test_bug1500(MYSQL *mysql)
|
||||
{
|
||||
MYSQL_STMT *stmt;
|
||||
MYSQL_BIND my_bind[3];
|
||||
int rc;
|
||||
int rc= 0;
|
||||
int32 int_data[3]= {2, 3, 4};
|
||||
const char *data;
|
||||
const char *query;
|
||||
char *data;
|
||||
char *query;
|
||||
|
||||
|
||||
rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_bg1500");
|
||||
@@ -1084,6 +1086,8 @@ static int test_bug20152(MYSQL *mysql)
|
||||
my_bind[0].buffer_type= MYSQL_TYPE_DATE;
|
||||
my_bind[0].buffer= (void*)&tm;
|
||||
|
||||
memset(&tm, 0, sizeof(MYSQL_TIME));
|
||||
|
||||
tm.year = 2006;
|
||||
tm.month = 6;
|
||||
tm.day = 18;
|
||||
@@ -2180,11 +2184,11 @@ static int test_bug4026(MYSQL *mysql)
|
||||
rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
|
||||
check_stmt_rc(rc, stmt);
|
||||
/* Bind input buffers */
|
||||
memset(my_bind, '\0', sizeof(my_bind));
|
||||
memset(&time_in, '\0', sizeof(time_in));
|
||||
memset(&time_out, '\0', sizeof(time_out));
|
||||
memset(&datetime_in, '\0', sizeof(datetime_in));
|
||||
memset(&datetime_out, '\0', sizeof(datetime_out));
|
||||
memset(my_bind, '\0', sizeof(MYSQL_BIND) * 2);
|
||||
memset(&time_in, '\0', sizeof(MYSQL_TIME));
|
||||
memset(&time_out, '\0', sizeof(MYSQL_TIME));
|
||||
memset(&datetime_in, '\0', sizeof(MYSQL_TIME));
|
||||
memset(&datetime_out, '\0', sizeof(MYSQL_TIME));
|
||||
my_bind[0].buffer_type= MYSQL_TYPE_TIME;
|
||||
my_bind[0].buffer= (void *) &time_in;
|
||||
my_bind[1].buffer_type= MYSQL_TYPE_DATETIME;
|
||||
|
@@ -680,6 +680,9 @@ const char *ssl_cert_finger_print= "@SSL_CERT_FINGER_PRINT@";
|
||||
static int test_ssl_fp(MYSQL *unused)
|
||||
{
|
||||
MYSQL *my;
|
||||
MYSQL_RES *res;
|
||||
MYSQL_ROW row;
|
||||
int rc;
|
||||
|
||||
if (check_skip_ssl())
|
||||
return SKIP;
|
||||
@@ -695,6 +698,20 @@ static int test_ssl_fp(MYSQL *unused)
|
||||
port, socketname, 0), mysql_error(my));
|
||||
|
||||
FAIL_IF(check_cipher(my) != 0, "Invalid cipher");
|
||||
|
||||
mysql_query(my, "SET @a:=1");
|
||||
check_mysql_rc(rc, my);
|
||||
|
||||
mysql_query(my, "SELECT @a");
|
||||
check_mysql_rc(rc, my);
|
||||
|
||||
if ((res= mysql_store_result(my)))
|
||||
{
|
||||
row= mysql_fetch_row(res);
|
||||
diag("@a:=%s", row[0]);
|
||||
mysql_free_result(res);
|
||||
}
|
||||
|
||||
mysql_close(my);
|
||||
return OK;
|
||||
}
|
||||
|
Reference in New Issue
Block a user