5314 Ahmad Abdullateef 2013-01-02 [merge]
BUG#13934876 - SHARED MEMORY CONNECTIONS CRASH THE SERVER
WHEN ENDING
DESCRIPTION:
When mysqld is in shared memory mode under windows and
we stress test the server with a multi threaded client
which also randomly issues "kill connection" command
we see the mysqld process crashing randomly.
ANALYSIS :
When "kill connection xx" is received and executed on an
arbitrary thread it calls THD::shutdown_active_vio() on the
THD refered to by connection xx, this results in the
shared memory being unmapped. However the original thread
serving the connection xx might be in middle of a vio_read
or vio_write and it might end up accessing the unmapped
region of memory resulting in a crash.
FIX :
When "kill connection xx" is executed on an arbitrary thread it calls
THD::shutdown_active_vio() on the THD referred to by xx, this results in the
shared memory being unmapped. However the thread serving the connection xx
might be in middle of a vio_read or vio_write and it might end up accessing
the unmapped region of memory.
All handles are closed and the VIO is cleaned up when vio_delete() is
called and this completes the vio cleanup operation in its entirety.
All references to vio_close has been changed to vio_shutdown to cleanup code
and make its meaning relevant.
modified:
config.h.cmake
configure.cmake
include/violite.h
sql/rpl_slave.cc
sql/sql_class.cc
sql/sql_class.h
sql/sql_connect.cc
sql/sql_prepare.cc
vio/vio.c
vio/vio_priv.h
vio/viopipe.c
vio/vioshm.c
vio/viosocket.c
vio/viossl.c
5313 Ahmad Abdullateef 2013-01-02 [merge]
BUG#14792410 - INCONSISTENCY ABOUT MESSAGEFILE PATH NAME STYLE
IN MTR ON ALL PLATFORMS
DESCRIPTION:
Errors are printed in the Server logs when a directory containg errmsg.sys
is specified directly through the --lc-messages-dir or --language parameter.
FIX :
Improved the messaging and changed sql_print_error() to sql_print_warning().
modified:
sql/derror.cc
=== modified file 'config.h.cmake'
--- a/config.h.cmake 2012-12-18 08:54:05 +0000
+++ b/config.h.cmake 2013-01-02 08:09:22 +0000
@@ -495,7 +495,7 @@
#define MACHINE_TYPE "@MYSQL_MACHINE_TYPE@"
#cmakedefine HAVE_DTRACE 1
-#cmakedefine SIGNAL_WITH_VIO_CLOSE 1
+#cmakedefine SIGNAL_WITH_VIO_SHUTDOWN 1
/* Windows stuff, mostly functions, that have Posix analogs but named differently */
#cmakedefine S_IROTH @S_IROTH@
=== modified file 'configure.cmake'
--- a/configure.cmake 2012-11-23 13:12:26 +0000
+++ b/configure.cmake 2013-01-02 08:09:22 +0000
@@ -55,7 +55,7 @@ ENDIF()
# As a consequence of ALARMs no longer being used, thread
# notification for KILL must close the socket to wake up
# other threads.
-SET(SIGNAL_WITH_VIO_CLOSE 1)
+SET(SIGNAL_WITH_VIO_SHUTDOWN 1)
# Always enable -Wall for gnu C/C++
IF(CMAKE_COMPILER_IS_GNUCXX)
=== modified file 'include/violite.h'
--- a/include/violite.h 2012-11-06 09:20:51 +0000
+++ b/include/violite.h 2013-01-02 08:09:22 +0000
@@ -37,8 +37,8 @@ typedef struct st_vio Vio;
enum enum_vio_type
{
- VIO_CLOSED, VIO_TYPE_TCPIP, VIO_TYPE_SOCKET, VIO_TYPE_NAMEDPIPE,
- VIO_TYPE_SSL, VIO_TYPE_SHARED_MEMORY
+ VIO_TYPE_TCPIP, VIO_TYPE_SOCKET, VIO_TYPE_NAMEDPIPE, VIO_TYPE_SSL,
+ VIO_TYPE_SHARED_MEMORY
};
/**
@@ -71,19 +71,19 @@ Vio* vio_new_win32shared_memory(HANDLE h
#define HANDLE void *
#endif /* __WIN__ */
-void vio_delete(Vio* vio);
-int vio_close(Vio* vio);
+void vio_delete(Vio* vio);
+int vio_shutdown(Vio* vio);
my_bool vio_reset(Vio* vio, enum enum_vio_type type,
my_socket sd, void *ssl, uint flags);
-size_t vio_read(Vio *vio, uchar * buf, size_t size);
+size_t vio_read(Vio *vio, uchar * buf, size_t size);
size_t vio_read_buff(Vio *vio, uchar * buf, size_t size);
-size_t vio_write(Vio *vio, const uchar * buf, size_t size);
+size_t vio_write(Vio *vio, const uchar * buf, size_t size);
/* setsockopt TCP_NODELAY at IPPROTO_TCP level, when possible */
-int vio_fastsend(Vio *vio);
+int vio_fastsend(Vio *vio);
/* setsockopt SO_KEEPALIVE at SOL_SOCKET level, when possible */
-int vio_keepalive(Vio *vio, my_bool onoff);
+int vio_keepalive(Vio *vio, my_bool onoff);
/* Whenever we should retry the last read/write operation. */
-my_bool vio_should_retry(Vio *vio);
+my_bool vio_should_retry(Vio *vio);
/* Check that operation was timed out */
my_bool vio_was_timeout(Vio *vio);
/* Short text description of the socket for those, who are curious.. */
@@ -161,13 +161,13 @@ int sslconnect(struct st_VioSSLFd*, Vio
struct st_VioSSLFd
*new_VioSSLConnectorFd(const char *key_file, const char *cert_file,
- const char *ca_file, const char *ca_path,
- const char *cipher, enum enum_ssl_init_error *error,
+ const char *ca_file, const char *ca_path,
+ const char *cipher, enum enum_ssl_init_error *error,
const char *crl_file, const char *crl_path);
struct st_VioSSLFd
*new_VioSSLAcceptorFd(const char *key_file, const char *cert_file,
- const char *ca_file,const char *ca_path,
- const char *cipher, enum enum_ssl_init_error *error,
+ const char *ca_file,const char *ca_path,
+ const char *cipher, enum enum_ssl_init_error *error,
const char *crl_file, const char *crl_path);
void free_vio_ssl_acceptor_fd(struct st_VioSSLFd *fd);
#endif /* ! EMBEDDED_LIBRARY */
@@ -175,21 +175,21 @@ void free_vio_ssl_acceptor_fd(struct st_
void vio_end(void);
-#ifdef __cplusplus
+#ifdef __cplusplus
}
#endif
#if !defined(DONT_MAP_VIO)
-#define vio_delete(vio) (vio)->viodelete(vio)
-#define vio_errno(vio) (vio)->vioerrno(vio)
+#define vio_delete(vio) (vio)->viodelete(vio)
+#define vio_errno(vio) (vio)->vioerrno(vio)
#define vio_read(vio, buf, size) ((vio)->read)(vio,buf,size)
#define vio_write(vio, buf, size) ((vio)->write)(vio, buf, size)
-#define vio_fastsend(vio) (vio)->fastsend(vio)
-#define vio_keepalive(vio, set_keep_alive) (vio)->viokeepalive(vio, set_keep_alive)
-#define vio_should_retry(vio) (vio)->should_retry(vio)
+#define vio_fastsend(vio) (vio)->fastsend(vio)
+#define vio_keepalive(vio, set_keep_alive) (vio)->viokeepalive(vio, set_keep_alive)
+#define vio_should_retry(vio) (vio)->should_retry(vio)
#define vio_was_timeout(vio) (vio)->was_timeout(vio)
-#define vio_close(vio) ((vio)->vioclose)(vio)
-#define vio_peer_addr(vio, buf, prt, buflen) (vio)->peer_addr(vio, buf, prt, buflen)
+#define vio_shutdown(vio) ((vio)->vioshutdown)(vio)
+#define vio_peer_addr(vio, buf, prt, buflen) (vio)->peer_addr(vio, buf, prt, buflen)
#define vio_io_wait(vio, event, timeout) (vio)->io_wait(vio, event, timeout)
#define vio_is_connected(vio) (vio)->is_connected(vio)
#endif /* !defined(DONT_MAP_VIO) */
@@ -209,13 +209,14 @@ enum SSL_type
/* This structure is for every connection on both sides */
struct st_vio
{
- MYSQL_SOCKET mysql_socket; /* Instrumented socket */
- my_bool localhost; /* Are we from localhost? */
- struct sockaddr_storage local; /* Local internet address */
- struct sockaddr_storage remote; /* Remote internet address */
+ MYSQL_SOCKET mysql_socket; /* Instrumented socket */
+ my_bool localhost; /* Are we from localhost? */
+ struct sockaddr_storage local; /* Local internet address */
+ struct sockaddr_storage remote; /* Remote internet address */
int addrLen; /* Length of remote address */
- enum enum_vio_type type; /* Type of connection */
- char desc[VIO_DESCRIPTION_SIZE]; /* Description string. This
+ enum enum_vio_type type; /* Type of connection */
+ my_bool inactive; /* Connection inactive (has been shutdown) */
+ char desc[VIO_DESCRIPTION_SIZE]; /* Description string. This
member MUST NOT be
used directly, but only
via function
@@ -226,7 +227,16 @@ struct st_vio
char *read_end; /* end of unfetched data */
int read_timeout; /* Timeout value (ms) for read ops. */
int write_timeout; /* Timeout value (ms) for write ops. */
- /* function pointers. They are similar for socket/SSL/whatever */
+
+ /*
+ VIO vtable interface to be implemented by VIO's like SSL, Socket,
+ Named Pipe, etc.
+ */
+
+ /*
+ viodelete is responsible for cleaning up the VIO object by freeing
+ internal buffers, closing descriptors, handles.
+ */
void (*viodelete)(Vio*);
int (*vioerrno)(Vio*);
size_t (*read)(Vio*, uchar *, size_t);
@@ -238,7 +248,12 @@ struct st_vio
void (*in_addr)(Vio*, struct sockaddr_storage*);
my_bool (*should_retry)(Vio*);
my_bool (*was_timeout)(Vio*);
- int (*vioclose)(Vio*);
+ /*
+ vioshutdown is resposnible to shutdown/close the channel, so that no
+ further communications can take place, however any related buffers,
+ descriptors, handles can remain valid after a shutdown.
+ */
+ int (*vioshutdown)(Vio*);
my_bool (*is_connected)(Vio*);
my_bool (*has_data) (Vio*);
int (*io_wait)(Vio*, enum enum_vio_io_event, int);
@@ -248,7 +263,7 @@ struct st_vio
HANDLE hPipe;
#endif
#ifdef HAVE_OPENSSL
- void *ssl_arg;
+ void *ssl_arg;
#endif
#ifdef HAVE_SMEM
HANDLE handle_file_map;
=== modified file 'sql/rpl_slave.cc'
--- a/sql/rpl_slave.cc 2012-12-14 15:20:59 +0000
+++ b/sql/rpl_slave.cc 2013-01-02 08:09:22 +0000
@@ -3883,7 +3883,7 @@ static int try_to_reconnect(THD *thd, MY
{
mi->slave_running= MYSQL_SLAVE_RUN_NOT_CONNECT;
thd->proc_info= messages[SLAVE_RECON_MSG_WAIT];
-#ifdef SIGNAL_WITH_VIO_CLOSE
+#ifdef SIGNAL_WITH_VIO_SHUTDOWN
thd->clear_active_vio();
#endif
end_server(mysql);
@@ -4291,11 +4291,11 @@ err:
Here we need to clear the active VIO before closing the
connection with the master. The reason is that THD::awake()
might be called from terminate_slave_thread() because somebody
- issued a STOP SLAVE. If that happends, the close_active_vio()
+ issued a STOP SLAVE. If that happends, the shutdown_active_vio()
can be called in the middle of closing the VIO associated with
the 'mysql' object, causing a crash.
*/
-#ifdef SIGNAL_WITH_VIO_CLOSE
+#ifdef SIGNAL_WITH_VIO_SHUTDOWN
thd->clear_active_vio();
#endif
mysql_close(mysql);
@@ -6576,7 +6576,7 @@ err:
extern "C" void slave_io_thread_detach_vio()
{
-#ifdef SIGNAL_WITH_VIO_CLOSE
+#ifdef SIGNAL_WITH_VIO_SHUTDOWN
THD *thd= current_thd;
if (thd && thd->slave_thread)
thd->clear_active_vio();
@@ -6754,7 +6754,7 @@ replication resumed in log '%s' at posit
general_log_print(thd, COM_CONNECT_OUT, "%s@%s:%d",
mi->get_user(), mi->host, mi->port);
}
-#ifdef SIGNAL_WITH_VIO_CLOSE
+#ifdef SIGNAL_WITH_VIO_SHUTDOWN
thd->set_active_vio(mysql->net.vio);
#endif
}
=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc 2012-12-19 09:35:15 +0000
+++ b/sql/sql_class.cc 2013-01-02 08:09:22 +0000
@@ -329,7 +329,7 @@ void thd_unlock_thread_count(THD *)
void thd_close_connection(THD *thd)
{
if (thd->net.vio)
- vio_close(thd->net.vio);
+ vio_shutdown(thd->net.vio);
}
/**
@@ -988,7 +988,7 @@ THD::THD(bool enable_plugins)
peer_port= 0; // For SHOW PROCESSLIST
transaction.m_pending_rows_event= 0;
transaction.flags.enabled= true;
-#ifdef SIGNAL_WITH_VIO_CLOSE
+#ifdef SIGNAL_WITH_VIO_SHUTDOWN
active_vio = 0;
#endif
mysql_mutex_init(key_LOCK_thd_data, &LOCK_thd_data, MY_MUTEX_INIT_FAST);
@@ -1711,7 +1711,7 @@ void THD::awake(THD::killed_state state_
if (state_to_set != THD::KILL_QUERY)
{
-#ifdef SIGNAL_WITH_VIO_CLOSE
+#ifdef SIGNAL_WITH_VIO_SHUTDOWN
if (this != current_thd)
{
/*
@@ -1740,7 +1740,7 @@ void THD::awake(THD::killed_state state_
reading the next statement.
*/
- close_active_vio();
+ shutdown_active_vio();
}
#endif
@@ -1809,20 +1809,20 @@ void THD::disconnect()
killed= THD::KILL_CONNECTION;
-#ifdef SIGNAL_WITH_VIO_CLOSE
+#ifdef SIGNAL_WITH_VIO_SHUTDOWN
/*
Since a active vio might might have not been set yet, in
any case save a reference to avoid closing a inexistent
one or closing the vio twice if there is a active one.
*/
vio= active_vio;
- close_active_vio();
+ shutdown_active_vio();
#endif
/* Disconnect even if a active vio is not associated. */
if (net.vio != vio && net.vio != NULL)
{
- vio_close(net.vio);
+ vio_shutdown(net.vio);
}
mysql_mutex_unlock(&LOCK_thd_data);
@@ -2269,15 +2269,15 @@ int THD::send_explain_fields(select_resu
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF));
}
-#ifdef SIGNAL_WITH_VIO_CLOSE
-void THD::close_active_vio()
+#ifdef SIGNAL_WITH_VIO_SHUTDOWN
+void THD::shutdown_active_vio()
{
- DBUG_ENTER("close_active_vio");
+ DBUG_ENTER("shutdown_active_vio");
mysql_mutex_assert_owner(&LOCK_thd_data);
#ifndef EMBEDDED_LIBRARY
if (active_vio)
{
- vio_close(active_vio);
+ vio_shutdown(active_vio);
active_vio = 0;
}
#endif
=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h 2012-12-13 11:16:18 +0000
+++ b/sql/sql_class.h 2013-01-02 08:09:22 +0000
@@ -2389,7 +2389,7 @@ public:
#ifndef __WIN__
sigset_t signals;
#endif
-#ifdef SIGNAL_WITH_VIO_CLOSE
+#ifdef SIGNAL_WITH_VIO_SHUTDOWN
Vio* active_vio;
#endif
/*
@@ -3009,7 +3009,7 @@ public:
void cleanup_after_query();
bool store_globals();
bool restore_globals();
-#ifdef SIGNAL_WITH_VIO_CLOSE
+#ifdef SIGNAL_WITH_VIO_SHUTDOWN
inline void set_active_vio(Vio* vio)
{
mysql_mutex_lock(&LOCK_thd_data);
@@ -3022,7 +3022,7 @@ public:
active_vio = 0;
mysql_mutex_unlock(&LOCK_thd_data);
}
- void close_active_vio();
+ void shutdown_active_vio();
#endif
void awake(THD::killed_state state_to_set);
=== modified file 'sql/sql_connect.cc'
--- a/sql/sql_connect.cc 2012-11-21 12:44:48 +0000
+++ b/sql/sql_connect.cc 2013-01-02 08:09:22 +0000
@@ -501,7 +501,7 @@ static int check_connection(THD *thd)
DBUG_PRINT("info",
("New connection received on %s", vio_description(net->vio)));
-#ifdef SIGNAL_WITH_VIO_CLOSE
+#ifdef SIGNAL_WITH_VIO_SHUTDOWN
thd->set_active_vio(net->vio);
#endif
=== modified file 'sql/sql_prepare.cc'
--- a/sql/sql_prepare.cc 2012-11-21 12:44:48 +0000
+++ b/sql/sql_prepare.cc 2013-01-02 08:09:22 +0000
@@ -2644,7 +2644,7 @@ void mysqld_stmt_execute(THD *thd, char
sp_cache_enforce_limit(thd->sp_func_cache, stored_program_cache_size);
/* Close connection socket; for use with client testing (Bug#43560). */
- DBUG_EXECUTE_IF("close_conn_after_stmt_execute", vio_close(thd->net.vio););
+ DBUG_EXECUTE_IF("close_conn_after_stmt_execute", vio_shutdown(thd->net.vio););
DBUG_VOID_RETURN;
}
=== modified file 'vio/vio.c'
--- a/vio/vio.c 2012-12-11 15:56:03 +0000
+++ b/vio/vio.c 2013-01-02 08:09:22 +0000
@@ -84,7 +84,7 @@ static void vio_init(Vio *vio, enum enum
vio->viokeepalive =vio_keepalive;
vio->should_retry =vio_should_retry;
vio->was_timeout =vio_was_timeout;
- vio->vioclose =vio_close_pipe;
+ vio->vioshutdown =vio_shutdown_pipe;
vio->peer_addr =vio_peer_addr;
vio->io_wait =no_io_wait;
vio->is_connected =vio_is_connected_pipe;
@@ -95,7 +95,7 @@ static void vio_init(Vio *vio, enum enum
#ifdef HAVE_SMEM
if (type == VIO_TYPE_SHARED_MEMORY)
{
- vio->viodelete =vio_delete;
+ vio->viodelete =vio_delete_shared_memory;
vio->vioerrno =vio_errno;
vio->read =vio_read_shared_memory;
vio->write =vio_write_shared_memory;
@@ -103,7 +103,7 @@ static void vio_init(Vio *vio, enum enum
vio->viokeepalive =vio_keepalive;
vio->should_retry =vio_should_retry;
vio->was_timeout =vio_was_timeout;
- vio->vioclose =vio_close_shared_memory;
+ vio->vioshutdown =vio_shutdown_shared_memory;
vio->peer_addr =vio_peer_addr;
vio->io_wait =no_io_wait;
vio->is_connected =vio_is_connected_shared_memory;
@@ -122,7 +122,7 @@ static void vio_init(Vio *vio, enum enum
vio->viokeepalive =vio_keepalive;
vio->should_retry =vio_should_retry;
vio->was_timeout =vio_was_timeout;
- vio->vioclose =vio_ssl_close;
+ vio->vioshutdown =vio_ssl_shutdown;
vio->peer_addr =vio_peer_addr;
vio->io_wait =vio_io_wait;
vio->is_connected =vio_is_connected;
@@ -139,7 +139,7 @@ static void vio_init(Vio *vio, enum enum
vio->viokeepalive =vio_keepalive;
vio->should_retry =vio_should_retry;
vio->was_timeout =vio_was_timeout;
- vio->vioclose =vio_close;
+ vio->vioshutdown =vio_shutdown;
vio->peer_addr =vio_peer_addr;
vio->io_wait =vio_io_wait;
vio->is_connected =vio_is_connected;
@@ -335,8 +335,8 @@ void vio_delete(Vio* vio)
if (!vio)
return; /* It must be safe to delete null pointers. */
- if (vio->type != VIO_CLOSED)
- vio->vioclose(vio);
+ if (vio->inactive == FALSE)
+ vio->vioshutdown(vio);
my_free(vio->read_buffer);
my_free(vio);
}
=== modified file 'vio/vio_priv.h'
--- a/vio/vio_priv.h 2011-09-07 10:08:09 +0000
+++ b/vio/vio_priv.h 2013-01-02 07:54:14 +0000
@@ -29,14 +29,15 @@
size_t vio_read_pipe(Vio *vio, uchar * buf, size_t size);
size_t vio_write_pipe(Vio *vio, const uchar * buf, size_t size);
my_bool vio_is_connected_pipe(Vio *vio);
-int vio_close_pipe(Vio * vio);
+int vio_shutdown_pipe(Vio * vio);
#endif
#ifdef HAVE_SMEM
size_t vio_read_shared_memory(Vio *vio, uchar * buf, size_t size);
size_t vio_write_shared_memory(Vio *vio, const uchar * buf, size_t size);
my_bool vio_is_connected_shared_memory(Vio *vio);
-int vio_close_shared_memory(Vio * vio);
+int vio_shutdown_shared_memory(Vio * vio);
+void vio_delete_shared_memory(Vio *vio);
#endif
my_bool vio_buff_has_data(Vio *vio);
@@ -50,7 +51,7 @@ size_t vio_ssl_read(Vio *vio,uchar* buf,
size_t vio_ssl_write(Vio *vio,const uchar* buf, size_t size);
/* When the workday is over... */
-int vio_ssl_close(Vio *vio);
+int vio_ssl_shutdown(Vio *vio);
void vio_ssl_delete(Vio *vio);
my_bool vio_ssl_has_data(Vio *vio);
=== modified file 'vio/viopipe.c'
--- a/vio/viopipe.c 2011-06-06 19:57:05 +0000
+++ b/vio/viopipe.c 2013-01-02 07:54:14 +0000
@@ -101,17 +101,17 @@ my_bool vio_is_connected_pipe(Vio *vio)
}
-int vio_close_pipe(Vio *vio)
+int vio_shutdown_pipe(Vio *vio)
{
BOOL ret;
- DBUG_ENTER("vio_close_pipe");
+ DBUG_ENTER("vio_shutdown_pipe");
CancelIo(vio->hPipe);
CloseHandle(vio->overlapped.hEvent);
DisconnectNamedPipe(vio->hPipe);
ret= CloseHandle(vio->hPipe);
- vio->type= VIO_CLOSED;
+ vio->inactive= TRUE;
vio->hPipe= NULL;
vio->mysql_socket= MYSQL_INVALID_SOCKET;
=== modified file 'vio/vioshm.c'
--- a/vio/vioshm.c 2011-06-06 19:57:05 +0000
+++ b/vio/vioshm.c 2013-01-02 07:54:14 +0000
@@ -43,7 +43,7 @@ size_t vio_read_shared_memory(Vio *vio,
FALSE, timeout);
/*
- WaitForMultipleObjects can return next values:
+ WaitForMultipleObjects can return next values:
WAIT_OBJECT_0+0 - event from vio->event_server_wrote
WAIT_OBJECT_0+1 - event from vio->event_conn_closed.
We can't read anything
@@ -153,64 +153,73 @@ my_bool vio_is_connected_shared_memory(V
}
-/**
- Close shared memory and DBUG_PRINT any errors that happen on closing.
- @return Zero if all closing functions succeed, and nonzero otherwise.
+void vio_delete_shared_memory(Vio *vio)
+{
+ DBUG_ENTER("vio_delete_shared_memory");
+
+ if (!vio)
+ DBUG_VOID_RETURN;
+
+ if (vio->inactive == FALSE)
+ vio->vioshutdown(vio);
+
+ /*
+ Close all handlers. UnmapViewOfFile and CloseHandle return non-zero
+ result if they are success.
+ */
+ if (UnmapViewOfFile(vio->handle_map) == 0)
+ DBUG_PRINT("vio_error", ("UnmapViewOfFile() failed"));
+
+ if (CloseHandle(vio->event_server_wrote) == 0)
+ DBUG_PRINT("vio_error", ("CloseHandle(vio->esw) failed"));
+
+ if (CloseHandle(vio->event_server_read) == 0)
+ DBUG_PRINT("vio_error", ("CloseHandle(vio->esr) failed"));
+
+ if (CloseHandle(vio->event_client_wrote) == 0)
+ DBUG_PRINT("vio_error", ("CloseHandle(vio->ecw) failed"));
+
+ if (CloseHandle(vio->event_client_read) == 0)
+ DBUG_PRINT("vio_error", ("CloseHandle(vio->ecr) failed"));
+
+ if (CloseHandle(vio->handle_file_map) == 0)
+ DBUG_PRINT("vio_error", ("CloseHandle(vio->hfm) failed"));
+
+ if (CloseHandle(vio->event_conn_closed) == 0)
+ DBUG_PRINT("vio_error", ("CloseHandle(vio->ecc) failed"));
+
+ vio_delete(vio);
+
+ DBUG_VOID_RETURN;
+}
+
+/*
+ When "kill connection xx" is executed on an arbitrary thread it calls
+ THD::shutdown_active_vio() on the THD referred to by xx. Since the
+ thread serving the connection xx might be in the middle of a vio_read
+ or vio_write, we cannot unmap the shared memory here.
+
+ Therefore we here just signal the connection_closed event and give
+ the thread servicing connection xx a chance to gracefully exit.
+ All handles are closed and the VIO is cleaned up when vio_delete() is
+ called and this completes the vio cleanup operation in its entirety.
*/
-int vio_close_shared_memory(Vio * vio)
+int vio_shutdown_shared_memory(Vio * vio)
{
- int error_count= 0;
- DBUG_ENTER("vio_close_shared_memory");
- if (vio->type != VIO_CLOSED)
+ DBUG_ENTER("vio_shutdown_shared_memory");
+ if (vio->inactive == FALSE)
{
/*
Set event_conn_closed for notification of both client and server that
connection is closed
*/
SetEvent(vio->event_conn_closed);
- /*
- Close all handlers. UnmapViewOfFile and CloseHandle return non-zero
- result if they are success.
- */
- if (UnmapViewOfFile(vio->handle_map) == 0)
- {
- error_count++;
- DBUG_PRINT("vio_error", ("UnmapViewOfFile() failed"));
- }
- if (CloseHandle(vio->event_server_wrote) == 0)
- {
- error_count++;
- DBUG_PRINT("vio_error", ("CloseHandle(vio->esw) failed"));
- }
- if (CloseHandle(vio->event_server_read) == 0)
- {
- error_count++;
- DBUG_PRINT("vio_error", ("CloseHandle(vio->esr) failed"));
- }
- if (CloseHandle(vio->event_client_wrote) == 0)
- {
- error_count++;
- DBUG_PRINT("vio_error", ("CloseHandle(vio->ecw) failed"));
- }
- if (CloseHandle(vio->event_client_read) == 0)
- {
- error_count++;
- DBUG_PRINT("vio_error", ("CloseHandle(vio->ecr) failed"));
- }
- if (CloseHandle(vio->handle_file_map) == 0)
- {
- error_count++;
- DBUG_PRINT("vio_error", ("CloseHandle(vio->hfm) failed"));
- }
- if (CloseHandle(vio->event_conn_closed) == 0)
- {
- error_count++;
- DBUG_PRINT("vio_error", ("CloseHandle(vio->ecc) failed"));
- }
}
- vio->type= VIO_CLOSED;
+
+ vio->inactive= TRUE;
vio->mysql_socket= MYSQL_INVALID_SOCKET;
- DBUG_RETURN(error_count);
+
+ DBUG_RETURN(0);
}
#endif /* #if defined(_WIN32) && defined(HAVE_SMEM) */
=== modified file 'vio/viosocket.c'
--- a/vio/viosocket.c 2012-11-09 12:19:42 +0000
+++ b/vio/viosocket.c 2013-01-02 08:09:22 +0000
@@ -400,12 +400,12 @@ vio_was_timeout(Vio *vio)
}
-int vio_close(Vio * vio)
+int vio_shutdown(Vio * vio)
{
int r=0;
- DBUG_ENTER("vio_close");
+ DBUG_ENTER("vio_shutdown");
- if (vio->type != VIO_CLOSED)
+ if (vio->inactive == FALSE)
{
DBUG_ASSERT(vio->type == VIO_TYPE_TCPIP ||
vio->type == VIO_TYPE_SOCKET ||
@@ -422,7 +422,7 @@ int vio_close(Vio * vio)
DBUG_PRINT("vio_error", ("close() failed, error: %d",socket_errno));
/* FIXME: error handling (not critical for MySQL) */
}
- vio->type= VIO_CLOSED;
+ vio->inactive= TRUE;
vio->mysql_socket= MYSQL_INVALID_SOCKET;
DBUG_RETURN(r);
}
=== modified file 'vio/viossl.c'
--- a/vio/viossl.c 2011-09-07 10:08:09 +0000
+++ b/vio/viossl.c 2013-01-02 07:54:14 +0000
@@ -210,11 +210,11 @@ static long yassl_send(void *ptr, const
#endif
-int vio_ssl_close(Vio *vio)
+int vio_ssl_shutdown(Vio *vio)
{
int r= 0;
SSL *ssl= (SSL*)vio->ssl_arg;
- DBUG_ENTER("vio_ssl_close");
+ DBUG_ENTER("vio_ssl_shutdown");
if (ssl)
{
@@ -245,7 +245,7 @@ int vio_ssl_close(Vio *vio)
break;
}
}
- DBUG_RETURN(vio_close(vio));
+ DBUG_RETURN(vio_shutdown(vio));
}
@@ -254,8 +254,8 @@ void vio_ssl_delete(Vio *vio)
if (!vio)
return; /* It must be safe to delete null pointer */
- if (vio->type == VIO_TYPE_SSL)
- vio_ssl_close(vio); /* Still open, close connection first */
+ if (vio->inactive == FALSE)
+ vio_ssl_shutdown(vio); /* Still open, close connection first */
if (vio->ssl_arg)
{
No bundle (reason: useless for push emails).
| Thread |
|---|
| • bzr push into mysql-trunk branch (ahmad.abdullateef:5313 to 5314)Bug#13934876 | ahmad.abdullateef | 26 Jan 2013 |